diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..759e5e9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.errorSquiggles": "Disabled" +} diff --git a/Office Door/.pio/build/esp32dev/idedata.json b/Office Door/.pio/build/esp32dev/idedata.json new file mode 100644 index 0000000..09d7761 --- /dev/null +++ b/Office Door/.pio/build/esp32dev/idedata.json @@ -0,0 +1 @@ +{"env_name": "esp32dev", "libsource_dirs": ["/home/developer/Web3E-Application/Office Door/lib", "/home/developer/Web3E-Application/Office Door/.pio/libdeps/esp32dev", "/home/developer/.platformio/lib", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries"], "defines": ["PLATFORMIO=50200", "ARDUINO_ESP32_DEV", "ESP32", "ESP_PLATFORM", "F_CPU=240000000L", "HAVE_CONFIG_H", "MBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\"", "ARDUINO=10805", "ARDUINO_ARCH_ESP32", "ARDUINO_VARIANT=\"esp32\"", "ARDUINO_BOARD=\"Espressif ESP32 Dev Module\""], "includes": {"build": ["/home/developer/Web3E-Application/Office Door/include", "/home/developer/Web3E-Application/Office Door/src", "/home/developer/Web3E-Application/Office Door/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", "/home/developer/Web3E-Application/Office Door/.pio/libdeps/esp32dev/Web3E/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/config", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/app_trace", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/app_update", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/asio", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/bootloader_support", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/bt", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/coap", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/console", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/driver", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/efuse", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp-tls", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_adc_cal", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_event", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_http_client", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_http_server", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_https_ota", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_https_server", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_ringbuf", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_websocket_client", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/espcoredump", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/ethernet", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/expat", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fatfs", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/freemodbus", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/freertos", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/heap", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/idf_test", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/jsmn", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/json", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/libsodium", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/log", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/lwip", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mbedtls", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mdns", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/micro-ecc", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mqtt", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/newlib", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/nghttp", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/nvs_flash", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/openssl", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/protobuf-c", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/protocomm", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/pthread", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/sdmmc", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/smartconfig_ack", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/soc", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/spi_flash", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/spiffs", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/tcp_transport", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/tcpip_adapter", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/ulp", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/unity", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/vfs", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wear_levelling", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wifi_provisioning", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wpa_supplicant", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/xtensa-debug-module", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp-face", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32-camera", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp-face", "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fb_gfx", "/home/developer/.platformio/packages/framework-arduinoespressif32/cores/esp32", "/home/developer/.platformio/packages/framework-arduinoespressif32/variants/esp32"], "compatlib": ["/home/developer/Web3E-Application/Office Door/.pio/libdeps/esp32dev/Web3E/src", "/home/developer/Web3E-Application/Office Door/.pio/libdeps/esp32dev/Web3E/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/ESP32/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/FFat/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/FS/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdate/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdateServer/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/NetBIOS/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/Preferences/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/SD/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/Update/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src", "/home/developer/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src"], "toolchain": ["/home/developer/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include/c++/5.2.0", "/home/developer/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include/c++/5.2.0/xtensa-esp32-elf", "/home/developer/.platformio/packages/toolchain-xtensa32/lib/gcc/xtensa-esp32-elf/5.2.0/include-fixed", "/home/developer/.platformio/packages/toolchain-xtensa32/lib/gcc/xtensa-esp32-elf/5.2.0/include", "/home/developer/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include"], "unity": []}, "cc_path": "/home/developer/.platformio/packages/toolchain-xtensa32/bin/xtensa-esp32-elf-gcc", "cxx_path": "/home/developer/.platformio/packages/toolchain-xtensa32/bin/xtensa-esp32-elf-g++", "gdb_path": "/home/developer/.platformio/packages/toolchain-xtensa32/bin/xtensa-esp32-elf-gdb", "prog_path": "/home/developer/Web3E-Application/Office Door/.pio/build/esp32dev/firmware.elf", "svd_path": null, "compiler_type": "gcc", "targets": [{"name": "buildfs", "title": "Build Filesystem Image", "description": null, "group": "Platform"}, {"name": "size", "title": "Program Size", "description": "Calculate program size", "group": "Platform"}, {"name": "upload", "title": "Upload", "description": null, "group": "Platform"}, {"name": "uploadfs", "title": "Upload Filesystem Image", "description": null, "group": "Platform"}, {"name": "uploadfsota", "title": "Upload Filesystem Image OTA", "description": null, "group": "Platform"}, {"name": "erase", "title": "Erase Flash", "description": null, "group": "Platform"}, {"name": "compiledb", "title": "Compilation Database", "description": "Generate compilation database `compile_commands.json`", "group": "Advanced"}, {"name": "clean", "title": "Clean", "group": "Generic"}], "extra": {"flash_images": [{"offset": "0x1000", "path": "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin"}, {"offset": "0x8000", "path": "/home/developer/Web3E-Application/Office Door/.pio/build/esp32dev/partitions.bin"}, {"offset": "0xe000", "path": "/home/developer/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin"}]}, "cc_flags": "-std=gnu99 -Wno-old-style-declaration -Os -g3 -Wall -nostdlib -Wpointer-arith -Wno-error=unused-but-set-variable -Wno-error=unused-variable -mlongcalls -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wno-error=deprecated-declarations -Wno-error=unused-function -Wno-unused-parameter -Wno-sign-compare -fstack-protector -fexceptions -Werror=reorder", "cxx_flags": "-fno-rtti -fno-exceptions -std=gnu++11 -Os -g3 -Wall -nostdlib -Wpointer-arith -Wno-error=unused-but-set-variable -Wno-error=unused-variable -mlongcalls -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wno-error=deprecated-declarations -Wno-error=unused-function -Wno-unused-parameter -Wno-sign-compare -fstack-protector -fexceptions -Werror=reorder"} \ No newline at end of file diff --git a/Office Door/.pio/build/project.checksum b/Office Door/.pio/build/project.checksum new file mode 100644 index 0000000..7d05648 --- /dev/null +++ b/Office Door/.pio/build/project.checksum @@ -0,0 +1 @@ +6267ff0de5f64c008486cb9c301cc10998ab4acb \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/.gitignore b/Office Door/.pio/libdeps/esp32dev/Web3E/.gitignore new file mode 100644 index 0000000..49a05e7 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/.gitignore @@ -0,0 +1,2 @@ +# Visual Studio Code project files +.vscode/ \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/.piopm b/Office Door/.pio/libdeps/esp32dev/Web3E/.piopm new file mode 100644 index 0000000..6f4a73e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/.piopm @@ -0,0 +1 @@ +{"type": "library", "name": "Web3E", "version": "1.10.0", "spec": {"owner": "alphawallet", "id": 5781, "name": "Web3E", "requirements": null, "url": null}} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/LICENSE b/Office Door/.pio/libdeps/esp32dev/Web3E/LICENSE new file mode 100644 index 0000000..c5502a8 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 Stormbird/Alpha Wallet + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/README.md b/Office Door/.pio/libdeps/esp32dev/Web3E/README.md new file mode 100644 index 0000000..1be4318 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/README.md @@ -0,0 +1,344 @@ +# Web3E Ethereum for Embedded devices + + + +## Version 1.10 + +Web3E is a fully functional Web3 framework for Embedded devices running Arduino. Web3E now has methods which allow you to use TokenScript in your IoT solution for rapid deployment. Tested mainly on ESP32 and working on ESP8266. Also included is a rapid development DApp injector to convert your embedded server into a fully integrated Ethereum DApp. + +Starting from a simple requirement - write a DApp capable of running on an ESP32 which can serve as a security door entry system. Some brave attempts can be found in scattered repos but ultimately even the best are just dapp veneers or have ingeneous and clunky hand-rolled communication systems like the Arduino wallet attempts. + +What is required is a method to write simple, fully embedded DApps which give you a zero infrastucture and total security solution. +It is possible that as Ethereum runs natively on embedded devices a new revolution in the blockchain saga will begin. Now you have the ability to write a fully embedded DApp that gives you the seurity and flexibility of Ethereum in an embedded device. + +## New Features + +- TokenScript/API interface [TokenScript](https://tokenscript.org) +- uint256 class added to correctly handle Ethereum types. +- usability methods added for converting between doubles and Wei values. +- usability methods added for displaying Wei values as doubles. +- random number generation uses Mersenne Twister. +- memory usage improved. + +## Features + +- Web3E now has a streamlined [TokenScript](https://tokenscript.org) interface for smooth integration with AlphaWallet, and other TokenScript powered wallet. +- Web3E has a Ready-to-Go DApp injection system that turns any device hosted site instantly into an Ethereum DApp with ECDSA crypto! +- Cryptography has been overhauled to use a cut-down version of Trezor Wallet's heavily optimised and production proven library. +- Transaction system is fully optimised and has been tested on ERC20 and ERC875 contracts. +- Usability has been a priority. + +## Installation + +- It is recommended to use [Platformio](https://platformio.org/install/) for best experience. Web3E is now part of the Platformio libraries so no need to clone the repo. +- Using Web3E is a one step process: + 1. Create a new project in Platformio and edit the platformio.ini so it looks similar to: + +``` +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino + +; Serial Monitor options +monitor_speed = 115200 + +lib_deps = + # Using a library name + Web3E +``` + +## Example TokenScript flow + +- Two API end points are exposed on the embedded device, '/api/getChallenge' and 'api/checkSignature?sig=' +- Device creates a challenge string, lets say 'Oranges 22853'. +- Tokenscript enabled phone runs embedded JavaScript that does a 'fetch' on 'getChallenge', returning 'Oranges 22853'. +- User is asked to sign this message using Ethereum SignPersonalMessage, with the same key that owns an entry token. +- Signature is sent back to embedded device using 'fetch' on 'api/checkSignature?sig='. +- Device ECRecover's an Ethereum Address from the signature using the current challenge. +- If address from ECRecover holds a token then open the door. +- Report pass/fail to callee. + +The advantage of using TokenScript rather than a dapp is evident from looking at the code example. You will have a very nice user interface defined with html/css with the calling code written in small JavaScript functions. The user would quickly find the entry token in their wallet. + +## Example Web3E DApp flow + +- Device creates a challenge string, lets say 'Oranges 22853'. +- Sign button containing a JavaScript Web3 call will instruct the wallet browser to ask the user to use their private key to sign 'Oranges 22853'. +- After user signs, the signature and the user's address are passed back into the code running on the firmware. +- Web3E can perform ECRecover on the signature and the challenge string it created. +- The device code compares the recovered address with the address from the user. If they match then we have verified the user holds the private key for that address. +- Web3E can now check for specific permission tokens held by the user address. If the tokens are present the user has permission to operate whatever is connected to the device, could be a security door, safe, the office printer, a shared bitcoin hardware wallet etc. +- All operations are offchain ie gasless, but using on-chain attestations which an owner can issue at will. + +## AlphaWallet Security Door + +https://github.com/alpha-wallet/Web3E-Application + +Full source code for the [system active at the AlphaWallet office](https://www.youtube.com/watch?v=D_pMOMxXrYY). To get it working you need: +- [Platformio](https://platformio.org/) +- [AlphaWallet](https://www.alphawallet.com) +- [Testnet Eth Kovan](https://faucet.kovan.network). Visit this site on the DApp browser. +- [Testnet Eth Goerli](https://goerli-faucet.slock.it/). Visit this site on your DApp browser. +Choose NonFungible token standard ERC721 or ERC875. Note the samples are written for ERC875 so you may need to adapt them for the ERC721 balance check. +- [Mint some ERC721 tokens](https://mintable.app/create) Visit here on your DApp browser. +- [Mint some ERC875 tokens](https://tf.alphawallet.com) Visit here on your DApp browser. +- Take a note of the contract address. Copy/paste contract address into source code inside the 'STORMBIRD_CONTRACT' define. +- Build and deploy the sample to your Arduino framework device. +- Use the transfer or MagicLink on AlphaWallet to give out the tokens. + +## Included in the package are seven samples + +- Simple DApp. Shows the power of the library to create a DApp server truly embedded in the device. The on-board cryptography engine can fully interact with user input. Signing, recovery/verification takes milliseconds on ESP32. +- Query Wallet balances, Token balances and for the first time Non-Fungible-Token (NFT) balances. +- Push transactions, showing token transfer of ERC20 and ERC875 tokens. +- Send Eth, showing how to send native eth. +- Wallet Bridge 1: Introduction to simple TokenScript connection to wallet. +- Wallet Bridge 2: Use simple authentication to check pre-defined addresses. +- Wallet Bridge 3: Use Ethereum Tokens as security attestations to interct with your IoT directly via the wallet. + +The push transaction sample requires a little work to get running. You have to have an Ethereum wallet, some testnet ETH, the private key for that testnet eth, and then create some ERC20 and ERC875 tokens in the account. + +## Usage +See Wallet Bridge 1, 2 and 3 examples for complete source + +## Standard: Using ScriptProxy Bridge +### This style of connection will work in almost every situation, from inside or outside of the WiFi connection +In this usage pattern, your IoT device will connect to a proxy server which provides a bridge to the TokenScript running on your wallet. +The source code for the proxy server can be found here: [Script Proxy](https://github.com/AlphaWallet/Web3E-Application/tree/master/ScriptProxy) + +- Set up API routes +``` + const char *apiRoute = "api/"; + enum APIRoutes { + api_getChallenge, + api_checkSignature, + api_End }; + + s_apiRoutes["getChallenge"] = api_getChallenge; + s_apiRoutes["checkSignature"] = api_checkSignature; + s_apiRoutes["end"] = api_End; +``` + +Declare UdpBridge, KeyID and Web3 in globals: + +``` +UdpBridge *udpConnection; +Web3 *web3; +KeyID *keyID; +``` + +Start UDP bridge after connecting to WiFi: + +``` + udpConnection = new UdpBridge(); + udpConnection->setKey(keyID, web3); + udpConnection->startConnection(); +``` + +Within your loop() check for API call: + +``` + udpConnection->checkClientAPI(&handleAPI); +``` + +Handle API call in the callback: + +``` +void handleAPI(APIReturn *apiReturn, UdpBridge *udpBridge, int methodId) +{ + switch (s_apiRoutes[apiReturn->apiName.c_str()]) + { + case api_getChallenge: + Serial.println(currentChallenge.c_str()); + udpBridge->sendResponse(currentChallenge, methodId); + break; + case api_checkSignature: + { + //EC-Recover address from signature and challenge + string address = Crypto::ECRecoverFromPersonalMessage(&apiReturn->params["sig"], ¤tChallenge); + //Check if this address has our entry token + boolean hasToken = QueryBalance(&address); + updateChallenge(); //generate a new challenge after each check + if (hasToken) + { + udpBridge->sendResponse("pass", methodId); + OpenDoor(); //Call your code that opens a door or performs the required 'pass' action + } + else + { + udpBridge->sendResponse("fail: doesn't have token", methodId); + } + } + break; +``` + + +## Advanced: Direct TCP connection +### Use this if you have admin control of your WiFi Router, as you need to set up port forwarding to access the unit from outside your WiFi +In this usage pattern, the TokenScript running on the wallet will connect directly to the IoT device. Notice that this means your IoT is directly accessible to the internet, which may be susceptible to exploit. + +- Declare the TCP server in globals: +``` +WiFiServer server(8082); +``` +- Ensure your Device is locked to a fixed IP Address for port forwarding (adjust local IP address as required): +``` +IPAddress ipStat(192, 168, 1, 100); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 255, 0); +IPAddress dns(192, 168, 1, 1); +WiFi.config(ipStat, gateway, subnet, dns, dns); +``` + + +- Set up API routes +``` + const char *apiRoute = "api/"; + enum APIRoutes { + api_getChallenge, + api_checkSignature, + api_End }; + + s_apiRoutes["getChallenge"] = api_getChallenge; + s_apiRoutes["checkSignature"] = api_checkSignature; + s_apiRoutes["end"] = api_End; +``` +- Listen for API call: +``` + WiFiClient c = server.available(); // Listen for incoming clients + ScriptClient *client = (ScriptClient*) &c; + + if (*client) + { + Serial.println("New Client."); + client->checkClientAPI(apiRoute, &handleAPI); //method handles connection close etc. + } +``` +- Handle API return: +``` +void handleAPI(APIReturn *apiReturn, ScriptClient *client) +{ + switch(s_apiRoutes[apiReturn->apiName.c_str()]) + { + case api_getChallenge: + client->print(currentChallenge.c_str()); + break; + case api_checkSignature: + { + //EC-Recover address from signature and challenge + string address = Crypto::ECRecoverFromPersonalMessage(&apiReturn->params["sig"], ¤tChallenge); + //Check if this address has our entry token + boolean hasToken = QueryBalance(&address); + updateChallenge(); //generate a new challenge after each check + if (hasToken) + { + client->print("pass"); + OpenDoor(); //Call your code that opens a door or performs the required 'pass' action + } + else + { + client->print("fail: doesn't have token"); + } + } + break; + } +``` + +## Ethereum transaction (ie send ETH to address): + +``` +// Setup Web3 and Contract with Private Key +... + +Contract contract(&web3, ""); +contract.SetPrivateKey(PRIVATE_KEY); +uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&address); //obtain the next nonce +uint256_t weiValue = Util::ConvertToWei(0.25, 18); //send 0.25 eth +unsigned long long gasPriceVal = 1000000000ULL; +uint32_t gasLimitVal = 90000; +string emptyString = ""; +string toAddress = "0xC067A53c91258ba513059919E03B81CF93f57Ac7"; +string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &toAddress, &weiValue, &emptyString); +``` + +## Query ETH balance: +``` +uint256_t balance = web3.EthGetBalance(&address); //obtain balance in Wei +string balanceStr = Util::ConvertWeiToEthString(&balance, 18); //get string balance as Eth (18 decimals) +``` + +## Query ERC20 Balance: +``` +string address = string("0x007bee82bdd9e866b2bd114780a47f2261c684e3"); +Contract contract(&web3, "0x20fe562d797a42dcb3399062ae9546cd06f63280"); //contract is on Ropsten + +//Obtain decimals to correctly display ERC20 balance (if you already know this you can skip this step) +string param = contract.SetupContractData("decimals()", &address); +string result = contract.ViewCall(¶m); +int decimals = web3.getInt(&result); + +//Fetch the balance in base units +param = contract.SetupContractData("balanceOf(address)", &address); +result = contract.ViewCall(¶m); + +uint256_t baseBalance = web3.getUint256(&result); +string balanceStr = Util::ConvertWeiToEthString(&baseBalance, decimals); //convert balance to double style using decimal places +``` + +## Send ERC20 Token: +``` +string contractAddr = "0x20fe562d797a42dcb3399062ae9546cd06f63280"; +Contract contract(&web3, contractAddr.c_str()); +contract.SetPrivateKey(); + +//Get contract name +string param = contract.SetupContractData("name()", &addr); +string result = contract.ViewCall(¶m); +string interpreted = Util::InterpretStringResult(web3.getString(&result).c_str()); +Serial.println(interpreted.c_str()); + +//Get Contract decimals +param = contract.SetupContractData("decimals()", &addr); +result = contract.ViewCall(¶m); +int decimals = web3.getInt(&result); +Serial.println(decimals); + +unsigned long long gasPriceVal = 22000000000ULL; +uint32_t gasLimitVal = 4300000; + +//amount of erc20 token to send, note we use decimal value obtained earlier +uint256_t weiValue = Util::ConvertToWei(0.1, decimals); + +//get nonce +uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&addr); +string toAddress = "0x007bee82bdd9e866b2bd114780a47f2261c684e3"; +string valueStr = "0x00"; + +//Setup contract function call +string p = contract.SetupContractData("transfer(address,uint256)", &toAddress, &weiValue); //ERC20 function plus params + +//push transaction to ethereum +result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &contractAddr, &valueStr, &p); +string transactionHash = web3.getString(&result); +``` + +Originally forked https://github.com/kopanitsa/web3-arduino but with almost a complete re-write it is a new framework entirely. + +Libraries used: +- Web3 Arduino https://github.com/kopanitsa/web3-arduino - skeleton of framework. +- Trezor Crypto https://github.com/trezor/trezor-crypto - ECDSA sign, recover, verify, keccak256. +- cJSON https://github.com/DaveGamble/cJSON +- uint256 https://github.com/calccrypto/uint256_t - Lightweight uint256 implementation perfect for embedded devices. +- Mersenne Twister https://github.com/MersenneTwister-Lab/TinyMT.git - For the most optimal random number generation for embedded. + +Coming soon: + +- Security door using NFT access (currently live at AlphaWallet office!). +- ERC1155 balance enquiry. +- Use Templates in library code for more flexible development. + +# Donations +If you support the cause, we could certainly use donations to help fund development: + +0xbc8dAfeacA658Ae0857C80D8Aa6dE4D487577c63 diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Push Transaction/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Push Transaction/main.cpp new file mode 100644 index 0000000..2a6f4a0 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Push Transaction/main.cpp @@ -0,0 +1,256 @@ +#include +#include +#include +#include + +// To get this sample working correctly there is some preparation work you need to do. +// Feel free to skip the majority of these instructions if you're an experienced ETH user - you probably just jump in at stage 6 +// If you already have Kovan or any other testnet ETH. +// +// 1. Choose an Ethereum test network (or if you're brave mainnet). I like Kovan as it's nice and fast. +// If you're using Infura you should sign up and use your own key. This is a test key I use, I wouldn't use it for anything serious. +// 2. Download a good ethereum wallet. The best one on Android and iOS is probably 'AlphaWallet' in the respective app stores. You +// can also use MetaMask on desktop which works fine, but doesn't display the Non-Fungible Token standards such as ERC875 and ERC1155. +// 3. In Metamask ensure you created an account. If you already have an account with mainnet ETH in it create a new one. +// Export the private key and import it into AlphaWallet (or just use the browser with Metamask). Also, +// Copy/Paste the private key into the 'PRIVATE_KEY' constant below. This is why you shouldn't use any account containing real eth. +// - you may accidentally commit the code to a public repo then you'll have all your eth gone very quickly. +// 4. Obtain some testnet Eth. If you're using Kovan there are two good faucets we know about: +// https://gitter.im/kovan-testnet/faucet : requres a github account. Just find your address in your wallet, +// and copy/paste it into the chat. The bot will pick it up and drop 3 ETH into your account. +// https://faucet.kovan.network/ : also requires github account and will give you 1 ETH per day. +// 5. Ensure that you switch network to Koven in the wallet. Got to settings and click on 'Network'. Select Kovan. +// 6. Create an ERC20 contract. Once you gave some Kovan in your wallet open the DApp browser in AlphaWallet and go here: +// http://thetokenfactory.com/#/factory Create a name and symbol for your token, +// choose 4 decimal places and a supply of say 5000000. This will give you 500 tokens in the account (50 0000 - 4 decimal places). +// 7. Click create and your wallet will receive a message to spend Kovan ETH to create the token. +// 8. Once the contract has been created and the tokens appear in your wallet copy/paste the contract address into ERC20CONTRACT below +// 9. To create ERC875 tokens go to this website in AlphaWallet or Metamask enabled desktop browser: +// https://alpha-wallet.github.io/ERC875-token-factory/index.html +// and just fill in name and symbol then create. The tokens will be assigned to the creation address. +// Once the tokens appear in your AlphaWallet, click on them and get the contract address (top right menu icon). +// Paste the contract address in the 'ERC875CONTRACT' setting below. +//10. Set up a second account in you wallet and copy the Address (not private key!) into the 'TARGETADDRESS' setting below. +// This way you get to catch all the sent tokens in your second account. + + +const char *ssid = ""; +const char *password = ""; +#define MY_ADDRESS "0xDA358D1547238335Cc666E318c511Fed455Ed77C" //Put your wallet address here +#define ERC875CONTRACT "0x0181540116ea1047d7b5a22ce3394d5cecc0c3f1" //Put your ERC875 contract address here +#define ERC20CONTRACT "0x0ab0c2f54afe26cbd2ed2b56a27816e41092d040" //Put your ERC20 contract address here +#define INFURA_HOST "kovan.infura.io" +#define INFURA_PATH "/v3/c7df4c29472d4d54a39f7aa78f146853" //please change this Infura key to your own once you have the sample running +#define TARGETADDRESS "0x007bEe82BDd9e866b2bd114780a47f2261C684E3" //put your second address here +#define ETHERSCAN_TX "https://kovan.etherscan.io/tx/" + +// Copy/paste the private key from MetaMask in here +const char *PRIVATE_KEY = "DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00"; //32 Byte Private key + +int wificounter = 0; +Web3 web3(INFURA_HOST, INFURA_PATH); + +void setup_wifi(); +void PushERC875Transaction(); +void queryERC875Balance(const char *userAddress); +void sendEthToAddress(double eth, const char *destination); +void PushERC20Transaction(double tokens, const char *toAddr, const char *contractAddr); + +void setup() { + Serial.begin(115200); + + setup_wifi(); + + sendEthToAddress(0.1, TARGETADDRESS); + PushERC20Transaction(0.1, TARGETADDRESS, ERC20CONTRACT); + queryERC875Balance(MY_ADDRESS); + PushERC20Transaction(); + PushERC875Transaction(); +} + +void loop() { + +} + +void sendEthToAddress(double eth, const char *destination) +{ + //obtain a contract object, for just sending eth doesn't need a contract address + Contract contract(&web3, ""); + contract.SetPrivateKey(PRIVATE_KEY); + unsigned long long gasPriceVal = 22000000000ULL; + uint32_t gasLimitVal = 90000; + string address = MY_ADDRESS; + + //convert eth value to Wei + uint256_t weiValue = Util::ConvertToWei(eth, 18); + string emptyString = ""; + string destinationAddress = destination; + + Serial.print("Get Nonce: "); + uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&address); + Serial.println(nonceVal); + Serial.println("Send TX"); + string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &destinationAddress, &weiValue, &emptyString); + Serial.println(result.c_str()); + + string transactionHash = web3.getString(&result); + Serial.println("TX on Etherscan:"); + Serial.print(ETHERSCAN_TX); + Serial.println(transactionHash.c_str()); //you can go straight to etherscan and see the pending transaction +} + +void PushERC20Transaction(double tokens, const char *toAddr, const char *contractAddr) +{ + string contractAddrStr = contractAddr; + Contract contract(&web3, contractAddr); + contract.SetPrivateKey(); + + //Get contract name (This isn't needed to push the transaction) + string param = contract.SetupContractData("name()", &addr); + string result = contract.ViewCall(¶m); + string interpreted = Util::InterpretStringResult(web3.getString(&result).c_str()); + Serial.println(interpreted.c_str()); + + //Get Contract decimals + param = contract.SetupContractData("decimals()", &addr); + result = contract.ViewCall(¶m); + int decimals = web3.getInt(&result); + Serial.println(decimals); + + unsigned long long gasPriceVal = 22000000000ULL; + uint32_t gasLimitVal = 4300000; + + //amount of erc20 token to send, note we use decimal value obtained earlier + uint256_t weiValue = Util::ConvertToWei(tokens, decimals); + + //get nonce + uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&addr); + string toAddress = toAddr; + string valueStr = "0x00"; + + //Setup contract function call + string p = contract.SetupContractData("transfer(address,uint256)", &toAddress, &weiValue); //ERC20 function plus params + + //push transaction to ethereum + result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &contractAddrStr, &valueStr, &p); + string transactionHash = web3.getString(&result); +} + + +/* Query balance of ERC875 tokens */ +void queryERC875Balance(const char *userAddress) +{ + // transaction + Contract contract(&web3, ERC875CONTRACT); + + String myAddr = userAddress; + + String func = "balanceOf(address)"; + Serial.println("Start"); + string param = contract.SetupContractData(func.c_str(), &myAddr); + string result = contract.ViewCall(¶m); + + Serial.println(result.c_str()); + + Serial.print("Balance of Contract "); + Serial.println(ERC875CONTRACT); + Serial.print("for user: "); + Serial.println(myAddr.c_str()); + Serial.println(); + + //break down the result + vector *vectorResult = Util::InterpretVectorResult(&result); + int count = 0; + char buffer[128]; + for (auto itr = vectorResult->begin(); itr != vectorResult->end(); itr++) + { + snprintf(buffer, 128, "%d: %s", count++, itr->c_str()); + Serial.println(buffer); + } + + delete(vectorResult); + + //Call contract name function + param = contract.SetupContractData("name()", &userAddress); + result = contract.ViewCall(¶m); + string contractName = web3.getString(&result); + Serial.println("NAME: "); + // recover actual string name + string interpreted = Util::InterpretStringResult(contractName.c_str()); + Serial.println(interpreted.c_str()); +} + +void PushERC875Transaction() +{ + Contract contract(&web3, ERC875CONTRACT); + contract.SetPrivateKey(PRIVATE_KEY); + string addr = MY_ADDRESS; + uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&addr); + + unsigned long long gasPriceVal = 22000000000ULL; + uint32_t gasLimitVal = 4300000; + uint8_t dataStr[100]; + memset(dataStr, 0, 100); + string address = TARGETADDRESS; + vector indices; + indices.push_back(1); // transfer NFT index 1 (ie the second token, since index 0 is the first token) + string p = contract.SetupContractData("transfer(address,uint256[])", &address, &indices); + string contractAddr = ERC875CONTRACT; + string valueStrThis = "0x00"; + + string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &contractAddr, &valueStrThis, &p); + Serial.println(result.c_str()); + string transactionHash = web3.getString(&result); + Serial.println("TX on Etherscan:"); + Serial.print(ETHERSCAN_TX); + Serial.println(transactionHash.c_str()); //you can go straight to etherscan and see the pending transaction +} + + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setup_wifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + + WiFi.begin(ssid, password); + } + + wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + for (int i = 0; i < 500; i++) + { + delay(1); + } + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Query Token Balance/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Query Token Balance/main.cpp new file mode 100644 index 0000000..8be3439 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Query Token Balance/main.cpp @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This sample should work straight 'out of the box' after you plug in your WiFi credentials + +const char *ssid = ""; +const char *password = ""; +const char *INFURA_HOST = "kovan.infura.io"; +const char *INFURA_PATH = "/v3/"; //this is an anonymous infura public API key for courtesy testing, please don't use it for production +#define NATIVE_ETH_TOKENS "Kovan ETH" //if you switch chains you might want to change this +#define ERC875CONTRACT "0x0b70dd9f8ada11eee393c8ab0dd0d3df6a172876" //an ERC875 token contract on Kovan +#define ERC20CONTRACT "0xb06d72a24df50d4e2cac133b320c5e7de3ef94cb" //and ERC20 token contract on Kovan +#define USERACCOUNT "0x835bb27deec61e1cd81b3a2feec9fbd76b15971d" //a user account that holds Kovan ETH and balances of tokens in the two above contracts + +Web3 web3(INFURA_HOST, INFURA_PATH); +int wificounter = 0; + +void queryERC875Balance(const char* Address, const char* ERC875ContractAddress); +void queryERC20Balance(const char* Address, const char* ERC875ContractAddress); +void setup_wifi(); +void TestERC20(); +void QueryEthBalance(const char* Address); + +void setup() +{ + Serial.begin(115200); //ensure you set your Arduino IDE port config or platformio.ini with monitor_speed = 115200 + setup_wifi(); + + string userAddress = USERACCOUNT; + + queryERC20Balance(ERC20CONTRACT, USERACCOUNT); + queryERC875Balance(ERC875CONTRACT, USERACCOUNT); +} + + +void loop() +{ + // put your main code here, to run repeatedly. +} + +/* Query balance of ERC875 tokens */ +void queryERC875Balance(const char* ContractAddress, const char *userAddress) +{ + // transaction + Contract contract(&web3, ContractAddress); + + String myAddr = userAddress; + + String func = "balanceOf(address)"; + Serial.println("Start"); + string param = contract.SetupContractData(func.c_str(), &myAddr); + string result = contract.ViewCall(¶m); + + Serial.println(result.c_str()); + + Serial.print("Balance of Contract "); + Serial.println(ContractAddress); + Serial.print("for user: "); + Serial.println(myAddr.c_str()); + Serial.println(); + + //break down the result + vector *vectorResult = Util::InterpretVectorResult(&result); + int count = 1; + char buffer[128]; + for (auto itr = vectorResult->begin(); itr != vectorResult->end(); itr++) + { + snprintf(buffer, 128, "%d: %s", count++, itr->c_str()); + Serial.println(buffer); + } + + delete(vectorResult); + + //Call contract name function + param = contract.SetupContractData("name()", &userAddress); + result = contract.ViewCall(¶m); + string contractName = web3.getString(&result); + Serial.println("NAME: "); + // recover actual string name + string interpreted = Util::InterpretStringResult(contractName.c_str()); + Serial.println(interpreted.c_str()); +} + +// Query balance of ERC20 token +void queryERC20Balance(const char* ContractAddress, const char *userAddress) +{ + Contract contract(&web3, contractAddr); + String address = userAddress; + string param = contract.SetupContractData("balanceOf(address)", &address); + string result = contract.ViewCall(¶m); + + param = contract.SetupContractData("decimals()", &address); + result = contract.ViewCall(¶m); + int decimals = web3.getInt(&result); + + uint256_t baseBalance = web3.getUint256(&result); + string balanceStr = Util::ConvertWeiToEthString(&baseBalance, decimals); //use decimals to calculate value, not all ERC20 use 18 decimals + + Serial.print("ERC20 Balance: "); + Serial.println(balanceStr.c_str()); +} + + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setup_wifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + + WiFi.begin(ssid, password); + } + + wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + for (int i = 0; i < 500; i++) + { + delay(1); + } + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Send Eth to Address/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Send Eth to Address/main.cpp new file mode 100644 index 0000000..2618ec4 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Send Eth to Address/main.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include + +// To get this sample working correctly there is some preparation work you need to do. +// Feel free to skip the majority of these instructions if you're an experienced ETH user - you probably just need +// to fill in your private key and accounts +// +// 1. Choose an Ethereum test network (or if you're brave mainnet). I like Kovan as it's nice and fast. +// If you're using Infura you should sign up and use your own key. This is a test key I use, I wouldn't use it for anything serious. +// 2. Download a good ethereum wallet. The best one on Android and iOS is probably 'AlphaWallet' in the respective app stores. You +// can also use MetaMask on desktop which works fine, but doesn't display the Non-Fungible Token standards such as ERC875 and ERC1155. +// 3. In Metamask ensure you created an account. If you already have an account with mainnet ETH in it create a new one. +// Export the private key and import it into AlphaWallet (or just use the browser with Metamask). Also, +// Copy/Paste the private key into the 'PRIVATE_KEY' constant below. This is why you shouldn't use any account containing real eth for testing. +// - you may accidentally commit the code to a public repo then you'll have all your eth gone very quickly. +// 4. Obtain some testnet Eth. If you're using Kovan there are two good faucets we know about: +// https://gitter.im/kovan-testnet/faucet : requres a github account. Just find your address in your wallet, +// and copy/paste it into the chat. The bot will pick it up and drop 3 ETH into your account. +// https://faucet.kovan.network/ : also requires github account and will give you 1 ETH per day. +// 5. Ensure that you switch network to Koven in the wallet. Got to settings and click on 'Network'. Select Kovan. +// 6. Set up a second account in you wallet and copy the Address (not private key!) into the 'TARGETADDRESS' setting below. +// This way you get to catch all the sent ETH in your second account. + + +const char *ssid = ""; +const char *password = ""; +#define MY_ADDRESS "0xDA358D1547238335Cc666E318c511Fed455Ed77C" //Put your wallet address here +#define INFURA_HOST "kovan.infura.io" +#define INFURA_PATH "/v3/c7df4c29472d4d54a39f7aa78f146853" //please change this Infura key to your own once you have the sample running +#define TARGETADDRESS "0x007bEe82BDd9e866b2bd114780a47f2261C684E3" //put your second address here +#define ETHERSCAN_TX "https://kovan.etherscan.io/tx/" + +// Copy/paste the private key from MetaMask in here +const char *PRIVATE_KEY = "DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00DabbaD00"; //32 Byte Private key + +int wificounter = 0; +Web3 web3(INFURA_HOST, INFURA_PATH); + +void setup_wifi(); +void sendEthToAddress(double eth, const char *destination); +double queryAccountBalance(const char *address); + +void setup() { + Serial.begin(115200); + + setup_wifi(); + + double balance = queryAccountBalance(MY_ADDRESS); + Serial.print("My Address: "); + Serial.println(MY_ADDRESS); + Serial.print("Balance of Address: "); + Serial.println(balance); + + Serial.println("Try to send 0.1 ETH"); + Serial.print("To Address: "); + Serial.println(TARGETADDRESS); + + if (balance < 0.11) //allow for gas + { + sendEthToAddress(0.1, TARGETADDRESS); + } + else + { + Serial.println("Balance is insufficient, cannot send ... Go to Eth faucet."); + } +} + +double queryAccountBalance(const char *address) +{ + uint256_t balance = web3.EthGetBalance(&address); //obtain balance in Wei + string balanceStr = Util::ConvertWeiToEthString(&balance, 18); //Eth uses 18 decimal + Serial.print("Balance: "); + Serial.println(balanceStr.c_str()); + double balanceDbl = atof(balanceStr.c_str()); + return balanceDbl; +} + +void sendEthToAddress(double eth, const char *destination) +{ + //obtain a contract object, for just sending eth doesn't need a contract address + Contract contract(&web3, ""); + contract.SetPrivateKey(PRIVATE_KEY); + unsigned long long gasPriceVal = 22000000000ULL; + uint32_t gasLimitVal = 90000; + + //convert eth value to Wei + uint256_t weiValue = Util::ConvertToWei(eth, 18); + string emptyString = ""; + string destinationAddress = destination; + + Serial.print("Get Nonce: "); + uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&address); + Serial.println(nonceVal); + Serial.println("Send TX"); + string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &destinationAddress, &weiValue, &emptyString); + Serial.println(result.c_str()); + + string transactionHash = web3.getString(&result); + Serial.println("TX on Etherscan:"); + Serial.print(ETHERSCAN_TX); + Serial.println(transactionHash.c_str()); //you can go straight to etherscan and see the pending transaction +} + +void loop() { + +} + + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setup_wifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + + WiFi.begin(ssid, password); + } + + wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + for (int i = 0; i < 500; i++) + { + delay(1); + } + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/.gitignore b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/platformio.ini b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/platformio.ini new file mode 100644 index 0000000..e850d49 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/platformio.ini @@ -0,0 +1,20 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino + +monitor_speed = 115200 + +lib_deps = + Web3E + Ticker \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/src/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/src/main.cpp new file mode 100644 index 0000000..0356598 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 1/src/main.cpp @@ -0,0 +1,194 @@ +/** + * Part 1 of TokenScript example + * + * This demo shows a very simple connection between wallet and IoT device + * To get up and running you will need to: + * 1. Install AlphaWallet on iOS or Android + * 2. Copy your wallet address from Settings/My Wallet Address + * 3. Visit the faucet here: https://goerli-faucet.slock.it/ and paste your address in the box and get some Goerli. You may want to repeat to get 0.1 Goerli. + * 4. Enable Goerli testnet in Settings/Networks and wait until you have Goerli in your wallet. The contract fee will be about 0.005 + * 5. In Dapp Browser ensure you are on Goerli network (top right network select button) type 'NFT' in the top URL bar and click on NFT Token Factory + * 6. Fill in Contract Name and Token Symbol with the text you want your test token to appear in the wallet and press Deploy. Other fields are optional. + * 7. When the contract is deployed and the tokens show up in the wallet you will need to find the contract address. + * Go to Transactions and look for the 'Constructor' call. Click this and find the Token address from the 'To:' field. Make a note of this address eg in Telegram/Saved Messages + * If you have iOS: find the latest 'Send' transaction with apparantely 0 eth, click for details then click on 'More Details' and get contract address on the webpage + * 8. Replace the text "" in the bundled .xml file with this token address. + * 9. Setup the WiFi in this program to your wifi credentials. + * 10. Flash this program to your ESP32/ESP8266 + * 11. Run the program and study the log for the Address. This is now the Device Address for this device. + * 12. Copy that address and replace "" in the bundled .xml file with the Device Address you created in step 11 + * 13. Send the .xml to your mobile phone via Telegram/Saved Messages or email etc. Click on the xml and open with AlphaWallet. + * 14. Open AlphaWallet and click on your token you created in step 6. + * 15. Long click on the token picture and select 'Action' + * 16. Wait to receive the challenge. Once received, sign the challenge, and once complete you should see the LED on the device blink. + * + * All the groundwork is now done to try the second and third examples. These will only require a simple update to get running. + * + **/ + +#include "esp_wifi.h" +#include +#include +#include +#include +#include +#include + +const char *ssid = "MySpectrumWiFi54-2G"; +const char *password = "littlebunny540"; + +const char *INFURA_HOST = "ropsten.infura.io"; +const char *INFURA_PATH = "/v3/5d99b4df68564865ab9814ee77f03b90"; + +#define BLUE_LED 22 // Little blue LED on the ESP32 TTGO + +UdpBridge *udpConnection; +Web3 web3(INFURA_HOST, INFURA_PATH); +KeyID *keyID; +std::string challenge; +boolean blinkLEDOn = false; + +void resetChallenge(); +void blink(); +void setupWifi(); +void handleUDPAPI(APIReturn *apiReturn, UdpBridge *udpBridge, int methodId); + +Ticker blinkTicker(blink, 500, 6); //ticker to blink the LED + +//define API routes +enum APIRoutes +{ + api_unknown, + api_getChallenge, + api_checkSignature, + api_End +}; + +std::map s_apiRoutes; + +//Format for API call from wallet/utilitiy using the bridge is //?=&= etc. +//When you call the API this is the extension you use EG www.bridgeserver.com/0x123456789ABCDEF0000/getChallenge +void Initialize() +{ + s_apiRoutes["getChallenge"] = api_getChallenge; + s_apiRoutes["checkSignature"] = api_checkSignature; + s_apiRoutes["end"] = api_End; + + random32v(micros()); //initial init of random seed AFTER wifi connection - since startup after wifi will be a different value of micros each start cycle +} + +void setup() +{ + Serial.begin(115200); + keyID = new KeyID(&web3); + pinMode(BLUE_LED, OUTPUT); + setupWifi(); + Initialize(); //init after wifi setup to change startup delay + + udpConnection = new UdpBridge(); + udpConnection->setKey(keyID, &web3); + udpConnection->startConnection(); + resetChallenge(); +} + +void loop() +{ + setupWifi(); + delay(1); + udpConnection->checkClientAPI(&handleUDPAPI); + blinkTicker.update(); +} + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setupWifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + } + + int wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + delay(500); + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + esp_wifi_set_ps(WIFI_PS_NONE); + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +// Handle API call from tokenscript +// NB: every path must return a response to the server via udpBridge->sendResponse(, methodId); +void handleUDPAPI(APIReturn *apiReturn, UdpBridge *udpBridge, int methodId) +{ + std::string address; + //handle the returned API call + Serial.println(apiReturn->apiName.c_str()); + + switch (s_apiRoutes[apiReturn->apiName.c_str()]) + { + case api_getChallenge: + resetChallenge(); //generate a new challenge after each check. Advantage is that we've done a full refresh of the mersenne twister + Serial.println(challenge.c_str()); + udpBridge->sendResponse(challenge, methodId); + break; + case api_checkSignature: + { + address = Crypto::ECRecoverFromPersonalMessage(&apiReturn->params["sig"], &challenge); + int intervalTime = strtol(apiReturn->params["interval"].c_str(), NULL, 10); + Serial.print("0x0000000000000000000000000000000000000000"); + Serial.println(address.c_str()); + blinkLEDOn = false; + if (intervalTime > 0) blinkTicker.interval(intervalTime); + blinkTicker.start(); + udpBridge->sendResponse("pass", methodId); + } + break; + default: + Serial.println("Unknown API route: "); + Serial.println(apiReturn->apiName.c_str()); + udpBridge->sendResponse("fail", methodId); + break; + } +} + +void resetChallenge() +{ + char buffer[32]; + long challengeVal = random32(); + challenge = "0x0000000000000000000000000000000000000000000000000000000000000000"; + challenge += itoa(challengeVal, buffer, 16); +} + +void blink() +{ + digitalWrite(BLUE_LED, blinkLEDOn); + blinkLEDOn = !blinkLEDOn; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/.gitignore b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/platformio.ini b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/platformio.ini new file mode 100644 index 0000000..e850d49 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/platformio.ini @@ -0,0 +1,20 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino + +monitor_speed = 115200 + +lib_deps = + Web3E + Ticker \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/src/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/src/main.cpp new file mode 100644 index 0000000..6d017e9 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 2/src/main.cpp @@ -0,0 +1,216 @@ +/** + * Part 2 of TokenScript example + * + * This demo builds on the example 1 adding cryptography and full but inflexible security + * To get up and running you will need to: + * 1. Complete Wallet Bridge 1 example + * 2. Fill in WiFi credentials. + * 3. Copy wallet address in AlphaWallet (Settings/My Wallet Address) and add into the 'allowedAccounts' below. You may add other accounts here too. + * 4. Flash the example and run on your ESP32/8266 + * 5. Find the token in AlphaWallet and click through to 'Action' + **/ + +#include "esp_wifi.h" +#include +#include +#include +#include +#include +#include + +const char *ssid = ""; +const char *password = " s_apiRoutes; + +//Format for API call from wallet/utilitiy using the bridge is //?=&= etc. +//When you call the API this is the extension you use EG www.bridgeserver.com/0x123456789ABCDEF0000/getChallenge +void Initialize() +{ + s_apiRoutes["getChallenge"] = api_getChallenge; + s_apiRoutes["checkSignature"] = api_checkSignature; + s_apiRoutes["end"] = api_End; + + random32v(micros()); //initial init of random seed AFTER wifi connection - since startup after wifi will be a different value of micros each start cycle +} + +void setup() +{ + Serial.begin(115200); + keyID = new KeyID(&web3); + pinMode(BLUE_LED, OUTPUT); + setupWifi(); + Initialize(); //init after wifi setup to change startup delay + + udpConnection = new UdpBridge(); + udpConnection->setKey(keyID, &web3); + udpConnection->startConnection(); + resetChallenge(); +} + +void loop() +{ + setupWifi(); + delay(1); + udpConnection->checkClientAPI(&handleUDPAPI); + blinkTicker.update(); +} + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setupWifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + } + + int wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + delay(500); + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + esp_wifi_set_ps(WIFI_PS_NONE); + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +// Handle API call from tokenscript +// NB: every path must return a response to the server via udpBridge->sendResponse(, methodId); +void handleUDPAPI(APIReturn *apiReturn, UdpBridge *udpBridge, int methodId) +{ + std::string address; + //handle the returned API call + Serial.println(apiReturn->apiName.c_str()); + + switch (s_apiRoutes[apiReturn->apiName.c_str()]) + { + case api_getChallenge: + Serial.println(challenge.c_str()); + udpBridge->sendResponse(challenge, methodId); + break; + case api_checkSignature: + { + address = Crypto::ECRecoverFromPersonalMessage(&apiReturn->params["sig"], &challenge); + int intervalTime = strtol(apiReturn->params["interval"].c_str(), NULL, 10); + Serial.print("EC-Addr: "); + Serial.println(address.c_str()); //The signer's address, ec-recover'd from the signature and challenge + if (isValidAccount(address)) //if address ec-recovered from signature matches one of the specified addresses then pass + { + blinkLEDOn = false; + if (intervalTime > 0) + blinkTicker.interval(intervalTime); + blinkTicker.start(); + udpBridge->sendResponse("pass", methodId); + } + else + { + udpBridge->sendResponse("fail : Invalid account", methodId); + } + resetChallenge(); //generate a new challenge after each check. + } + break; + default: + Serial.println("Unknown API route: "); + Serial.println(apiReturn->apiName.c_str()); + udpBridge->sendResponse("fail", methodId); + break; + } +} + +void resetChallenge() +{ + char buffer[32]; + long challengeVal = random32(); + challenge = "Sign This! "; + challenge += itoa(challengeVal, buffer, 16); +} + +void blink() +{ + digitalWrite(BLUE_LED, blinkLEDOn); + blinkLEDOn = !blinkLEDOn; +} + +bool iequals(const string &a, const string &b) +{ + unsigned int sz = a.size(); + if (b.size() != sz) + return false; + for (unsigned int i = 0; i < sz; ++i) + if (tolower(a[i]) != tolower(b[i])) + return false; + return true; +} + +boolean isValidAccount(std::string address) +{ + int accountsSize = (sizeof(allowedAccounts) / sizeof(*allowedAccounts)); + for (int index = 0; index < accountsSize; index++) + { + if (iequals(address, allowedAccounts[index])) + return true; + } + + return false; +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/.gitignore b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/platformio.ini b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/platformio.ini new file mode 100644 index 0000000..e850d49 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/platformio.ini @@ -0,0 +1,20 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino + +monitor_speed = 115200 + +lib_deps = + Web3E + Ticker \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/src/main.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/src/main.cpp new file mode 100644 index 0000000..bb36155 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/examples/Wallet Bridge 3/src/main.cpp @@ -0,0 +1,239 @@ +/** + * Part 3 of TokenScript example + * + * This demo builds on the example 2 adding Token checking. + * You can now transfer a token to another account and that account will be able to operate the device. + * To get up and running you will need to: + * 1. Complete Wallet Bridge 1 example to set up your contract + * 2. Fill in WiFi credentials. + * 3. Find the contract address from Example 1, setp 7 and add into the constant TOKEN_CONTRACT below + * 4. Flash the example and run on your ESP32/8266 + * 5. Find the token in AlphaWallet and click through to 'Action' + * 6. Create a new account in AlphaWallet. + * 7. Transfer the token to that account (you will have to copy the destination account to clipboard, then go to the previous account and transfer) + * 8. Verify the new account with the token can operate the device + **/ + +#include "esp_wifi.h" +#include +#include +#include +#include +#include +#include + +const char *ssid = ""; +const char *password = " s_apiRoutes; + +//Format for API call from wallet/utilitiy using the bridge is //?=&= etc. +//When you call the API this is the extension you use EG www.bridgeserver.com/0x123456789ABCDEF0000/getChallenge +void Initialize() +{ + s_apiRoutes["getChallenge"] = api_getChallenge; + s_apiRoutes["checkSignature"] = api_checkSignature; + s_apiRoutes["end"] = api_End; + + random32v(micros()); //initial init of random seed AFTER wifi connection - since startup after wifi will be a different value of micros each start cycle +} + +void setup() +{ + Serial.begin(115200); + keyID = new KeyID(&web3); + pinMode(BLUE_LED, OUTPUT); + digitalWrite(BLUE_LED, 0); + setupWifi(); + Initialize(); //init after wifi setup to change startup delay + + udpConnection = new UdpBridge(); + udpConnection->setKey(keyID, &web3); + udpConnection->startConnection(); + resetChallenge(); +} + +void loop() +{ + setupWifi(); + delay(1); + udpConnection->checkClientAPI(&handleUDPAPI); + blinkTicker.update(); +} + +/* This routine is specifically geared for ESP32 perculiarities */ +/* You may need to change the code as required */ +/* It should work on 8266 as well */ +void setupWifi() +{ + if (WiFi.status() == WL_CONNECTED) + { + return; + } + + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + if (WiFi.status() != WL_CONNECTED) + { + WiFi.persistent(false); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + } + + int wificounter = 0; + while (WiFi.status() != WL_CONNECTED && wificounter < 10) + { + delay(500); + Serial.print("."); + wificounter++; + } + + if (wificounter >= 10) + { + Serial.println("Restarting ..."); + ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this + } + + esp_wifi_set_ps(WIFI_PS_NONE); + delay(10); + + Serial.println(""); + Serial.println("WiFi connected."); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +// Handle API call from tokenscript +// NB: every path must return a response to the server via udpBridge->sendResponse(, methodId); +void handleUDPAPI(APIReturn *apiReturn, UdpBridge *udpBridge, int methodId) +{ + std::string address; + //handle the returned API call + Serial.println(apiReturn->apiName.c_str()); + + switch (s_apiRoutes[apiReturn->apiName.c_str()]) + { + case api_getChallenge: + resetChallenge(); //generate a new challenge after each check. Advantage is that we've done a full refresh of the mersenne twister + Serial.println(challenge.c_str()); + udpBridge->sendResponse(challenge, methodId); + break; + case api_checkSignature: + { + address = Crypto::ECRecoverFromPersonalMessage(&apiReturn->params["sig"], &challenge); + int intervalTime = strtol(apiReturn->params["interval"].c_str(), NULL, 10); + Serial.print("EC-Addr: "); + Serial.println(address.c_str()); + if (hasToken(address)) //Check if address is admin or has token + { + blinkLEDOn = false; + if (intervalTime > 0) + blinkTicker.interval(intervalTime); + blinkTicker.start(); //Perform PASS action + udpBridge->sendResponse("pass", methodId); + } + else + { + udpBridge->sendResponse("fail : Invalid account", methodId); + } + } + break; + default: + Serial.println("Unknown API route: "); + Serial.println(apiReturn->apiName.c_str()); + udpBridge->sendResponse("fail", methodId); + break; + } +} + +void resetChallenge() +{ + char buffer[32]; + long challengeVal = random32(); + challenge = "Sign This! "; + challenge += itoa(challengeVal, buffer, 16); +} + +void blink() +{ + blinkLEDOn = !blinkLEDOn; + digitalWrite(BLUE_LED, blinkLEDOn); +} + +bool hasToken(const std::string &userAddress) +{ + boolean hasToken = false; + const char *contractAddr = TOKEN_CONTRACT; + Contract contract(&web3, contractAddr); + string func = "balanceOf(address)"; + string param = contract.SetupContractData(func.c_str(), userAddress); + string result = contract.ViewCall(¶m); + + Serial.println(result.c_str()); + + BYTE tokenVal[32]; + + //break down the result + vector *vectorResult = Util::InterpretVectorResult(&result); + for (auto itr = vectorResult->begin(); itr != vectorResult->end(); itr++) + { + Util::ConvertHexToBytes(tokenVal, itr->c_str(), 32); + if (hasValue(tokenVal, 32)) + { + hasToken = true; + Serial.println("Has token"); + break; + } + } + + delete (vectorResult); + return hasToken; +} + +bool hasValue(BYTE *value, int length) +{ + for (int i = 0; i < length; i++) + { + if ((*value++) != 0) + { + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/keywords.txt b/Office Door/.pio/libdeps/esp32dev/Web3E/keywords.txt new file mode 100644 index 0000000..70e0c98 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/keywords.txt @@ -0,0 +1,96 @@ +####################################### + +# Syntax Coloring Map For Web3 + +####################################### + +# Class (KEYWORD1) + +####################################### + + + +Web3 KEYWORD1 + + + +####################################### + +# Methods and Functions (KEYWORD2) + +####################################### + + + +Web3ClientVersion KEYWORD2 +Web3Sha3 KEYWORD2 +NetVersion KEYWORD2 +NetListening KEYWORD2 +NetPeerCount KEYWORD2 +EthProtocolVersion KEYWORD2 +EthSyncing KEYWORD2 +EthMining KEYWORD2 +EthHashrate KEYWORD2 +EthGasPrice KEYWORD2 +EthAccounts KEYWORD2 +EthBlockNumber KEYWORD2 +EthGetBalance KEYWORD2 +EthGetTransactionCount KEYWORD2 +EthViewCall KEYWORD2 +UdpBridge KEYWORD2 +ScriptClient KEYWORD2 + +EthCall KEYWORD2 +EthSendSignedTransaction KEYWORD2 +getDAppCode KEYWORD2 + +getLongLong KEYWORD2 +getString KEYWORD2 +getInt KEYWORD2 + + +RlpEncodeWholeHeader KEYWORD2 +RlpEncodeWholeHeaderWithVector KEYWORD2 +RlpEncodeItem KEYWORD2 +RlpEncodeItemWithVector KEYWORD2 +ConvertNumberToUintArray KEYWORD2 +ConvertNumberToVector KEYWORD2 +ConvertCharStrToUintArray KEYWORD2 +ConvertHexToVector KEYWORD2 +ConvertToString KEYWORD2 + +HexToInt KEYWORD2 +VectorToCharStr KEYWORD2 +VectorToString KEYWORD2 +ConvertBytesToHex KEYWORD2 +ConvertHexToBytes KEYWORD2 +ConvertBase KEYWORD2 +ConvertDecimal KEYWORD2 +ConvertString KEYWORD2 +ConvertHexToASCII KEYWORD2 +InterpretStringResult KEYWORD2 +InterpretVectorResult KEYWORD2 +PadForward KEYWORD2 +ConvertCharStrToVector32 KEYWORD2 +Crypto KEYWORD2 +Sign KEYWORD2 +SetPrivateKey KEYWORD2 + +ECRecover KEYWORD2 +Verify KEYWORD2 +PrivateKeyToPublic KEYWORD2 +PublicKeyToAddress KEYWORD2 +Keccak256 KEYWORD2 + +Contract KEYWORD2 +SetPrivateKey KEYWORD2 +SetupContractData KEYWORD2 +Call KEYWORD2 +ViewCall KEYWORD2 +SendTransaction KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +BYTE LITERAL1 \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/library.json b/Office Door/.pio/libdeps/esp32dev/Web3E/library.json new file mode 100644 index 0000000..ea0fb6b --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/library.json @@ -0,0 +1,31 @@ +{ + "description": "Web3E (Ethereum Embedded) interface for devices running Arduino with easy to use TokenScript integration.", + "repository": { + "url": "https://github.com/AlphaWallet/Web3E", + "type": "git" + }, + "platforms": [ + "espressif32", + "espressif8266" + ], + "authors": [ + { + "maintainer": true, + "name": "James Brown", + "url": "https://github.com/JamesSmartCell", + "email": "james.brown@alphawallet.com" + } + ], + "frameworks": "arduino", + "keywords": [ + "Web3", + "Web3E", + "Ethereum", + "DApp", + "TokenScript", + "AlphaWallet" + ], + "name": "Web3E", + "version": "1.10", + "homepage": "https://alphawallet.com" +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/library.properties b/Office Door/.pio/libdeps/esp32dev/Web3E/library.properties new file mode 100644 index 0000000..ecd53b1 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/library.properties @@ -0,0 +1,10 @@ +name=Web3E +version=1.10 +author=James Brown +maintainer=James Brown +sentence=Web3E (Ethereum For Embedded) interface for Arduino and compitable devices. +paragraph=Web3E (Ethereum For Embedded) interface for Arduino and compitable devices. +category=Framework +url=https://github.com/AlphaWallet/Web3E +architectures=ESP32,ESP8266 +license=MIT diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/APIReturn.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/APIReturn.h new file mode 100644 index 0000000..a72a6dc --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/APIReturn.h @@ -0,0 +1,16 @@ +#ifndef _API_RETURN_H +#define _API_RETURN_H +#include +#include + +class APIReturn +{ +public: + APIReturn() { } + void clear() { apiName = ""; params.clear(); } + + std::string apiName; + std::map params; +}; + +#endif \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/CaCert.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/CaCert.h new file mode 100644 index 0000000..1d7e426 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/CaCert.h @@ -0,0 +1,26 @@ +const char* infura_ca_cert = \ +"-----BEGIN CERTIFICATE-----\n" \ +"MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx\n" \ +"EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n" \ +"HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs\n" \ +"ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5\n" \ +"MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD\n" \ +"VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy\n" \ +"ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy\n" \ +"dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI\n" \ +"hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p\n" \ +"OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2\n" \ +"8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K\n" \ +"Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe\n" \ +"hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk\n" \ +"6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw\n" \ +"DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q\n" \ +"AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI\n" \ +"bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB\n" \ +"ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z\n" \ +"qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd\n" \ +"iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn\n" \ +"0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN\n" \ +"sSi6\n" \ +"-----END CERTIFICATE-----\n" \ +; diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.cpp new file mode 100644 index 0000000..e274c2e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.cpp @@ -0,0 +1,321 @@ +// Web3E Contract handling code +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#include "Contract.h" +#include "Web3.h" +#include +#include "Util.h" +#include "cJSON/cJSON.h" +#include + +#define SIGNATURE_LENGTH 64 + +/** + * Public functions + * */ + +Contract::Contract(Web3* _web3, const char* address) { + web3 = _web3; + contractAddress = address; + options.gas=0; + strcpy(options.from,""); + strcpy(options.to,""); + strcpy(options.gasPrice,"0"); + crypto = NULL; +} + +void Contract::SetPrivateKey(const char *key) { + crypto = new Crypto(web3); + crypto->SetPrivateKey(key); +} + +string Contract::SetupContractData(const char* func, ...) +{ + string ret = ""; + + string contractBytes = GenerateContractBytes(func); + ret = contractBytes; + + size_t paramCount = 0; + vector params; + char *p; + char tmp[strlen(func)]; + memset(tmp, 0, sizeof(tmp)); + strcpy(tmp, func); + strtok(tmp, "("); + p = strtok(0, "("); + p = strtok(p, ")"); + p = strtok(p, ","); + if (p != 0) { + params.push_back(string(p)); + paramCount++; + } + while(p != 0) { + p = strtok(0, ","); + if (p != 0) + { + params.push_back(string(p)); + paramCount++; + } + } + + va_list args; + va_start(args, func); + for( int i = 0; i < paramCount; ++i ) { + if (strstr(params[i].c_str(), "uint") != NULL && strstr(params[i].c_str(), "[]") != NULL) + { + // value array + string output = GenerateBytesForUIntArray(va_arg(args, vector *)); + ret = ret + output; + } + else if (strncmp(params[i].c_str(), "uint", sizeof("uint")) == 0 || strncmp(params[i].c_str(), "uint256", sizeof("uint256")) == 0) + { + string output = GenerateBytesForUint(va_arg(args, uint256_t *)); + ret = ret + output; + } + else if (strncmp(params[i].c_str(), "int", sizeof("int")) == 0 || strncmp(params[i].c_str(), "bool", sizeof("bool")) == 0) + { + string output = GenerateBytesForInt(va_arg(args, int32_t)); + ret = ret + string(output); + } + else if (strncmp(params[i].c_str(), "address", sizeof("address")) == 0) + { + string output = GenerateBytesForAddress(va_arg(args, string *)); + ret = ret + string(output); + } + else if (strncmp(params[i].c_str(), "string", sizeof("string")) == 0) + { + string output = GenerateBytesForString(va_arg(args, string *)); + ret = ret + string(output); + } + else if (strncmp(params[i].c_str(), "bytes", sizeof("bytes")) == 0) + { + long len = strtol(params[i].c_str() + 5, nullptr, 10); + string output = GenerateBytesForBytes(va_arg(args, char *), len); + ret = ret + string(output); + } + } + va_end(args); + + return ret; +} + +string Contract::ViewCall(const string *param) +{ + string result = web3->EthViewCall(param, contractAddress); + return result; +} + +string Contract::Call(const string *param) +{ + const string from = string(options.from); + const long gasPrice = strtol(options.gasPrice, nullptr, 10); + const string value = ""; + + string result = web3->EthCall(&from, contractAddress, options.gas, gasPrice, &value, param); + return result; +} + +string Contract::SendTransaction(uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string *toStr, uint256_t *valueStr, string *dataStr) +{ + uint8_t signature[SIGNATURE_LENGTH]; + memset(signature, 0, SIGNATURE_LENGTH); + int recid[1] = {0}; + GenerateSignature(signature, recid, nonceVal, gasPriceVal, gasLimitVal, + toStr, valueStr, dataStr); + + vector param = RlpEncodeForRawTransaction(nonceVal, gasPriceVal, gasLimitVal, + toStr, valueStr, dataStr, + signature, recid[0]); + + string paramStr = Util::VectorToString(¶m); + return web3->EthSendSignedTransaction(¶mStr, param.size()); +} + +/** + * Private functions + **/ + +void Contract::GenerateSignature(uint8_t *signature, int *recid, uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string *toStr, uint256_t *valueStr, string *dataStr) +{ + vector encoded = RlpEncode(nonceVal, gasPriceVal, gasLimitVal, toStr, valueStr, dataStr); + // hash + string t = Util::VectorToString(&encoded); + + uint8_t *hash = new uint8_t[ETHERS_KECCAK256_LENGTH]; + size_t encodedTxBytesLength = (t.length()-2)/2; + uint8_t *bytes = new uint8_t[encodedTxBytesLength]; + Util::ConvertHexToBytes(bytes, t.c_str(), encodedTxBytesLength); + + Crypto::Keccak256((uint8_t*)bytes, encodedTxBytesLength, hash); + + // sign + Sign((uint8_t *)hash, signature, recid); +} + +std::string Contract::GenerateContractBytes(const char *func) +{ + std::string in = Util::ConvertBytesToHex((const uint8_t *)func, strlen(func)); + //get the hash of the input + std::vector contractBytes = Util::ConvertHexToVector(&in); + std::string out = Crypto::Keccak256(&contractBytes); + out.resize(10); + return out; +} + +string Contract::GenerateBytesForUint(const uint256_t *value) +{ + std::vector bits = value->export_bits(); + return Util::PlainVectorToString(&bits); +} + +string Contract::GenerateBytesForInt(const int32_t value) +{ + return string(56, '0') + Util::ConvertIntegerToBytes(value); +} + +string Contract::GenerateBytesForUIntArray(const vector *v) +{ + string dynamicMarker = std::string(64, '0'); + dynamicMarker.at(62) = '4'; //0x000...40 Array Designator + string arraySize = GenerateBytesForInt(v->size()); + string output = dynamicMarker + arraySize; + for (auto itr = v->begin(); itr != v->end(); itr++) + { + output += GenerateBytesForInt(*itr); + } + + return output; +} + +string Contract::GenerateBytesForAddress(const string *v) +{ + string cleaned = *v; + if (v->at(0) == 'x') cleaned = v->substr(1); + else if (v->at(1) == 'x') cleaned = v->substr(2); + size_t digits = cleaned.length(); + return string(64 - digits, '0') + cleaned; +} + +string Contract::GenerateBytesForString(const string *value) +{ + const char *valuePtr = value->c_str(); //don't fail if given a 'String' + size_t length = strlen(valuePtr); + return GenerateBytesForBytes(valuePtr, length); +} + +string Contract::GenerateBytesForBytes(const char *value, const int len) +{ + string bytesStr = Util::ConvertBytesToHex((const uint8_t *)value, len); + size_t digits = bytesStr.length(); + return bytesStr + string(64 - digits, '0'); +} + +vector Contract::RlpEncode( + uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string *toStr, uint256_t *val, string *dataStr) +{ + vector nonce = Util::ConvertNumberToVector(nonceVal); + vector gasPrice = Util::ConvertNumberToVector(gasPriceVal); + vector gasLimit = Util::ConvertNumberToVector(gasLimitVal); + vector to = Util::ConvertHexToVector(toStr); + vector value = val->export_bits_truncate(); + vector data = Util::ConvertHexToVector(dataStr); + + vector outputNonce = Util::RlpEncodeItemWithVector(nonce); + vector outputGasPrice = Util::RlpEncodeItemWithVector(gasPrice); + vector outputGasLimit = Util::RlpEncodeItemWithVector(gasLimit); + vector outputTo = Util::RlpEncodeItemWithVector(to); + vector outputValue = Util::RlpEncodeItemWithVector(value); + vector outputData = Util::RlpEncodeItemWithVector(data); + + vector encoded = Util::RlpEncodeWholeHeaderWithVector( + outputNonce.size() + + outputGasPrice.size() + + outputGasLimit.size() + + outputTo.size() + + outputValue.size() + + outputData.size()); + + encoded.insert(encoded.end(), outputNonce.begin(), outputNonce.end()); + encoded.insert(encoded.end(), outputGasPrice.begin(), outputGasPrice.end()); + encoded.insert(encoded.end(), outputGasLimit.begin(), outputGasLimit.end()); + encoded.insert(encoded.end(), outputTo.begin(), outputTo.end()); + encoded.insert(encoded.end(), outputValue.begin(), outputValue.end()); + encoded.insert(encoded.end(), outputData.begin(), outputData.end()); + + return encoded; +} + +void Contract::Sign(uint8_t *hash, uint8_t *sig, int *recid) +{ + BYTE fullSig[65]; + crypto->Sign(hash, fullSig); + *recid = fullSig[64]; + memcpy(sig,fullSig, 64); +} + +vector Contract::RlpEncodeForRawTransaction( + uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string *toStr, uint256_t *val, string *dataStr, uint8_t *sig, uint8_t recid) +{ + + vector signature; + for (int i = 0; i < SIGNATURE_LENGTH; i++) + { + signature.push_back(sig[i]); + } + vector nonce = Util::ConvertNumberToVector(nonceVal); + vector gasPrice = Util::ConvertNumberToVector(gasPriceVal); + vector gasLimit = Util::ConvertNumberToVector(gasLimitVal); + vector to = Util::ConvertHexToVector(toStr); + vector value = val->export_bits_truncate(); + vector data = Util::ConvertHexToVector(dataStr); + + vector outputNonce = Util::RlpEncodeItemWithVector(nonce); + vector outputGasPrice = Util::RlpEncodeItemWithVector(gasPrice); + vector outputGasLimit = Util::RlpEncodeItemWithVector(gasLimit); + vector outputTo = Util::RlpEncodeItemWithVector(to); + vector outputValue = Util::RlpEncodeItemWithVector(value); + vector outputData = Util::RlpEncodeItemWithVector(data); + + vector R; + R.insert(R.end(), signature.begin(), signature.begin()+(SIGNATURE_LENGTH/2)); + vector S; + S.insert(S.end(), signature.begin()+(SIGNATURE_LENGTH/2), signature.end()); + vector V; + V.push_back((uint8_t)(recid+27)); // 27 is a magic number for Ethereum spec + vector outputR = Util::RlpEncodeItemWithVector(R); + vector outputS = Util::RlpEncodeItemWithVector(S); + vector outputV = Util::RlpEncodeItemWithVector(V); + vector encoded = Util::RlpEncodeWholeHeaderWithVector( + outputNonce.size() + + outputGasPrice.size() + + outputGasLimit.size() + + outputTo.size() + + outputValue.size() + + outputData.size() + + outputR.size() + + outputS.size() + + outputV.size()); + + encoded.insert(encoded.end(), outputNonce.begin(), outputNonce.end()); + encoded.insert(encoded.end(), outputGasPrice.begin(), outputGasPrice.end()); + encoded.insert(encoded.end(), outputGasLimit.begin(), outputGasLimit.end()); + encoded.insert(encoded.end(), outputTo.begin(), outputTo.end()); + encoded.insert(encoded.end(), outputValue.begin(), outputValue.end()); + encoded.insert(encoded.end(), outputData.begin(), outputData.end()); + encoded.insert(encoded.end(), outputV.begin(), outputV.end()); + encoded.insert(encoded.end(), outputR.begin(), outputR.end()); + encoded.insert(encoded.end(), outputS.begin(), outputS.end()); + + return encoded; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.h new file mode 100644 index 0000000..f8fe087 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Contract.h @@ -0,0 +1,67 @@ +// Web3E Contract handling code +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#ifndef ARDUINO_WEB3_CONTRACT_H +#define ARDUINO_WEB3_CONTRACT_H + +#include "Arduino.h" +#include "Web3.h" +#include +#include +#include "uint256/uint256_t.h" + +using namespace std; + +class Contract { + +public: + typedef struct { + char from[80]; + char to[80]; + char gasPrice[20]; + long gas; + } Options; + Options options; + +public: + Contract(Web3* _web3, const char* address); + void SetPrivateKey(const char *key); + string SetupContractData(const char* func, ...); + string Call(const string* param); + string ViewCall(const string *param); + string SendTransaction(uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string *toStr, uint256_t *valueStr, string *dataStr); + +private: + Web3* web3; + const char * contractAddress; + Crypto* crypto; + +private: + string GenerateContractBytes(const char *func); + string GenerateBytesForInt(const int32_t value); + string GenerateBytesForUint(const uint256_t *value); + string GenerateBytesForAddress(const string *value); + string GenerateBytesForString(const string *value); + string GenerateBytesForBytes(const char* value, const int len); + string GenerateBytesForUIntArray(const vector *v); + + void GenerateSignature(uint8_t* signature, int* recid, uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string* toStr, uint256_t* valueStr, string* dataStr); + vector RlpEncode( + uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string* toStr, uint256_t* valueStr, string* dataStr); + vector RlpEncodeForRawTransaction( + uint32_t nonceVal, unsigned long long gasPriceVal, uint32_t gasLimitVal, + string* toStr, uint256_t* valueStr, string* dataStr, uint8_t* sig, uint8_t recid); + void Sign(uint8_t* hash, uint8_t* sig, int* recid); +}; + + +#endif //ARDUINO_WEB3_CONTRACT_H diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.cpp new file mode 100644 index 0000000..ceadad6 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.cpp @@ -0,0 +1,143 @@ +// +// Created by James Brown on 2018/09/13. +// + +#include +#include "Crypto.h" +#include "Web3.h" +#include "Util.h" +#include "Trezor/secp256k1.h" +#include "Trezor/ecdsa.h" +#include +#include + +#define SIGNATURE_LENGTH 64 + +using namespace std; + +const char * PERSONAL_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; + +Crypto::Crypto(Web3* _web3) +{ + web3 = _web3; + memset(privateKey, 0, ETHERS_PRIVATEKEY_LENGTH); +} + +bool Crypto::Sign(BYTE* digest, BYTE* result) +{ + const ecdsa_curve *curve = &secp256k1; + uint8_t pby; + int res = 0; + bool allZero = true; + for (int i = 0; i < ETHERS_PRIVATEKEY_LENGTH; i++) if (privateKey[i] != 0) allZero = false; + if (allZero == true) + { + Serial.println("Private key not set, generate a private key (eg use Metamask) and call Contract::SetPrivateKey with it."); + } + else + { + res = ecdsa_sign_digest(curve, privateKey, digest, result, &pby, NULL); + result[64] = pby; + } + + return (res == 1); +} + +void Crypto::SetPrivateKey(const char *key) +{ + Util::ConvertHexToBytes(privateKey, key, ETHERS_PRIVATEKEY_LENGTH); +} + +void Crypto::ECRecover(BYTE* signature, BYTE *public_key, BYTE *message_hash) +{ + uint8_t v = signature[64]; //recover 'v' from end of signature + uint8_t pubkey[65]; + uint8_t signature64[64]; + if (v > 26) v -= 27; //correct value of 'v' if required + memcpy(signature64, signature, 64); + const ecdsa_curve *curve = &secp256k1; + ecdsa_recover_pub_from_sig (curve, pubkey, signature, message_hash, v); + memcpy(public_key, pubkey+1, 64); +} + +bool Crypto::Verify(const uint8_t *public_key, const uint8_t *message_hash, const uint8_t *signature) +{ + const ecdsa_curve *curve = &secp256k1; + BYTE publicKey4[65]; + memcpy(publicKey4+1, public_key, 64); + publicKey4[0] = 4; + int success = ecdsa_verify_digest(curve, publicKey4, signature, message_hash); + return (success == 0); +} + +void Crypto::PrivateKeyToPublic(const uint8_t *privateKey, uint8_t *publicKey) +{ + uint8_t buffer[65]; + const ecdsa_curve *curve = &secp256k1; + ecdsa_get_public_key65(curve, privateKey, buffer); + memcpy(publicKey, buffer+1, 64); +} + +void Crypto::PublicKeyToAddress(const uint8_t *publicKey, uint8_t *address) +{ + uint8_t hashed[32]; + Keccak256(publicKey, 64, hashed); + memcpy(address, &hashed[12], 20); +} + +void Crypto::Keccak256(const uint8_t *data, uint16_t length, uint8_t *result) +{ + keccak_256(data, length, result); +} + +string Crypto::Keccak256(vector *bytes) +{ + uint8_t result[ETHERS_KECCAK256_LENGTH]; + keccak_256(bytes->data(), bytes->size(), result); + //now convert result to hex string + + vector resultVector; + for (int i = 0; i < ETHERS_KECCAK256_LENGTH; i++) resultVector.push_back(result[i]); + + return Util::VectorToString(&resultVector); +} + +string Crypto::ECRecoverFromHexMessage(string *signature, string *message) +{ + uint8_t challengeHash[ETHERS_KECCAK256_LENGTH]; + //convert hex to bytes + vector messageBytes = Util::ConvertHexToVector((uint8_t*)(message->c_str())); + //hash the full challenge + Crypto::Keccak256((uint8_t*)messageBytes.data(), messageBytes.size(), challengeHash); + return ECRecoverFromHash(signature, challengeHash); +} + +string Crypto::ECRecoverFromHash(string *signature, BYTE *digest) +{ + //convert address to BYTE + BYTE signatureBytes[ETHERS_SIGNATURE_LENGTH]; + BYTE publicKeyBytes[ETHERS_PUBLICKEY_LENGTH]; + + Util::ConvertHexToBytes(signatureBytes, signature->c_str(), ETHERS_SIGNATURE_LENGTH); + + // Perform ECRecover to get the public key - this extracts the public key of the private key + // that was used to sign the message - that is, the private key held by the wallet/metamask + Crypto::ECRecover(signatureBytes, publicKeyBytes, digest); + + BYTE recoverAddr[ETHERS_ADDRESS_LENGTH]; + // Now reduce the recovered public key to Ethereum address + Crypto::PublicKeyToAddress(publicKeyBytes, recoverAddr); + string recoveredAddress = Util::ConvertBytesToHex(recoverAddr, ETHERS_ADDRESS_LENGTH); + return recoveredAddress; +} + +string Crypto::ECRecoverFromPersonalMessage(string *signature, string *message) +{ + uint8_t challengeHash[ETHERS_KECCAK256_LENGTH]; + string challengeStr = PERSONAL_MESSAGE_PREFIX; + challengeStr += Util::toString((int)message->length()); + challengeStr += *message; + + Crypto::Keccak256((uint8_t*)challengeStr.c_str(), challengeStr.length(), challengeHash); + return ECRecoverFromHash(signature, challengeHash); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.h new file mode 100644 index 0000000..da38df0 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Crypto.h @@ -0,0 +1,40 @@ +// +// Created by James Brown on 2018/09/13. +// + +#ifndef ARDUINO_WEB3_CRYPTO_H +#define ARDUINO_WEB3_CRYPTO_H +#include "Web3.h" +#include + +using namespace std; + +extern const char * PERSONAL_MESSAGE_PREFIX; + +class Crypto { + +public: + Crypto(Web3* _web3); + bool Sign(BYTE* digest, BYTE* result); + void SetPrivateKey(const char *key); + + static void ECRecover(BYTE* signature, BYTE *public_key, BYTE *message_hash); + static bool Verify(const uint8_t *public_key, const uint8_t *message_hash, const uint8_t *signature); + static void PrivateKeyToPublic(const uint8_t *privateKey, uint8_t *publicKey); + static void PublicKeyToAddress(const uint8_t *publicKey, uint8_t *address); + static void Keccak256(const uint8_t *data, uint16_t length, uint8_t *result); + static string ECRecoverFromPersonalMessage(string *signature, string *message); + static string ECRecoverFromHexMessage(string *signature, string *hex); + static string ECRecoverFromHash(string *signature, BYTE *digest); + + static string Keccak256(vector *bytes); + + +private: + Web3* web3; + uint8_t privateKey[ETHERS_PRIVATEKEY_LENGTH]; + +}; + + +#endif //ARDUINO_WEB3_CRYPTO_H diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.cpp new file mode 100644 index 0000000..89d1128 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.cpp @@ -0,0 +1,91 @@ +#include +#include "Util.h" + + +KeyID::KeyID(Web3* web3) +{ + recoveredKey = false; + //private key is two 64 bytes, can do this by generating random bytes until we have 64 hex digits + std::string privateKey = ""; + privateKeyBytes = new BYTE[ETHERS_PRIVATEKEY_LENGTH]; + + if (!EEPROM.begin(EEPROM_SIZE+1)) + { + Serial.println("failed to initialise EEPROM"); + delay(1000000); + return; + } + + //fitst see if there's a stored key + if (byte(EEPROM.read(0)) == 64) + { + Serial.println(); + Serial.println("Recovering key from EEPROM"); + for (int i = 0; i < ETHERS_PRIVATEKEY_LENGTH; i++) + { + privateKeyBytes[i] = byte(EEPROM.read(i+1)); + } + + privateKey = Util::ConvertBytesToHex(privateKeyBytes, ETHERS_PRIVATEKEY_LENGTH); + if (privateKey[1] == 'x') privateKey.substr(2); + + initPrivateKey(privateKey, web3); + } +} + +void KeyID::generatePrivateKey(Web3* web3) +{ + random_buffer(privateKeyBytes, ETHERS_PRIVATEKEY_LENGTH); + + std::string privateKey = Util::ConvertBytesToHex(privateKeyBytes, ETHERS_PRIVATEKEY_LENGTH); + + Serial.print("Got Private Key: "); + Serial.println(privateKey.c_str()); + + EEPROM.write(0, 64); + for (int i = 0; i < ETHERS_PRIVATEKEY_LENGTH; i++) + { + EEPROM.write(i+1, privateKeyBytes[i]); + } + + EEPROM.commit(); + + initPrivateKey(privateKey, web3); +} + +void KeyID::getSignature(uint8_t* signature, BYTE *msgBytes) +{ + if (recoveredKey == false) return; + //need to convert uint32_t to byte + uint8_t hash[ETHERS_KECCAK256_LENGTH]; + + Serial.println(Util::ConvertBytesToHex(msgBytes, 8).c_str()); + + Crypto::Keccak256((uint8_t *)msgBytes, 8, hash); + Serial.print("Got Hash: "); + Serial.println(Util::ConvertBytesToHex(hash, ETHERS_KECCAK256_LENGTH).c_str()); + crypto->Sign(hash, signature); + Serial.print("Got Sig: "); + Serial.println(Util::ConvertBytesToHex(signature, ETHERS_SIGNATURE_LENGTH).c_str()); +} + +void KeyID::initPrivateKey(const std::string& privateKey, Web3* web3) +{ + crypto = new Crypto(web3); + crypto->SetPrivateKey(privateKey.c_str()); + recoveredKey = true; + getAddress(); +} + +const std::string KeyID::getAddress() +{ + BYTE ethAddressBytes[ETHERS_PUBLICKEY_LENGTH]; + BYTE publicKey[ETHERS_PUBLICKEY_LENGTH]; + + Crypto::PrivateKeyToPublic(privateKeyBytes, publicKey); + Crypto::PublicKeyToAddress(publicKey, ethAddressBytes); + Serial.print("Address: "); + std::string address = Util::ConvertBytesToHex(ethAddressBytes, ETHERS_ADDRESS_LENGTH); + Serial.println(address.c_str()); + return address; +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.h new file mode 100644 index 0000000..efb697c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/KeyID.h @@ -0,0 +1,28 @@ +#ifndef KEY_ID_H +#define KEY_ID_H +#include "EEPROM.h" +#include +#include +#include +#include + +#define EEPROM_SIZE ETHERS_PRIVATEKEY_LENGTH + +class KeyID +{ +public: + KeyID(Web3* web3); + void generatePrivateKey(Web3* web3); + void getSignature(uint8_t* signature, BYTE *msgBytes); + const std::string getAddress(); + bool hasRecoveredKey() { return recoveredKey; }; + +private: + void initPrivateKey(const std::string& privateKey, Web3* web3); + + BYTE *privateKeyBytes; + bool recoveredKey; + Crypto *crypto; +}; + +#endif \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.cpp new file mode 100644 index 0000000..47bb905 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.cpp @@ -0,0 +1,106 @@ +#include + +static std::string *sc_data = NULL; +static APIReturn *apiReturn = NULL; + +void ScriptClient::checkClientAPI(const char *route, APICallback callback) +{ + boolean currentLineIsBlank = true; + String currentLine = ""; // make a String to hold incoming data from the client + int timeout = 0; + if (sc_data == NULL) sc_data = new std::string(); + + while (connected()) + { + if (available()) + { + timeout = 0; + // if there's bytes to read from the client, + char c = read(); // read a byte, then + Serial.write(c); // print it out the serial monitor + *sc_data += c; + if (c == '\n' && currentLineIsBlank) + { + scanAPI(route, callback); + break; + } + if (c == '\n') + { // if you got a newline, then clear currentLine + currentLine = ""; + currentLineIsBlank = true; + } + else if (c != '\r') + { + currentLineIsBlank = false; + currentLine += c; + } + } + else + { + delay(1); + if (timeout++ > 500) + break; + } + } + + //Ensure connection is always closed after opening + closeConnection(); +} + +void ScriptClient::scanAPI(const char *route, APICallback callback) +{ + println("HTTP/1.1 200 OK"); + println("Content-type:text/html"); + println("Access-Control-Allow-Origin: *"); + println("Connection: close"); + println(); + + if (sc_data->find("favicon") != std::string::npos) + { + return; + } + + if (apiReturn == NULL) apiReturn = new APIReturn(); + apiReturn->clear(); + + size_t parseIndex = sc_data->find(route); + size_t endParseIndex = sc_data->find(" HTTP/"); + if (endParseIndex == std::string::npos) endParseIndex = sc_data->find(" HTTPS/"); + sc_data->erase(endParseIndex, sc_data->size() - endParseIndex); + parseIndex += strlen(route); + + if (parseIndex != std::string::npos) + { + size_t routeNameIndex = sc_data->find_first_of("?", parseIndex); + if (routeNameIndex == std::string::npos) routeNameIndex = sc_data->size(); + + apiReturn->apiName = sc_data->substr(parseIndex, routeNameIndex - parseIndex); + + parseIndex = routeNameIndex + 1; + + while (parseIndex < sc_data->size() && parseIndex < endParseIndex) + { + size_t keySeparatorIndex = sc_data->find_first_of("=", parseIndex); + size_t paramEndIndex = sc_data->find_first_of("&", keySeparatorIndex); + if (keySeparatorIndex == std::string::npos) break; + if (paramEndIndex == std::string::npos) paramEndIndex = sc_data->size(); + std::string key = sc_data->substr(parseIndex, keySeparatorIndex - parseIndex); + keySeparatorIndex++; + std::string param = sc_data->substr(keySeparatorIndex, paramEndIndex - keySeparatorIndex); + apiReturn->params[key] = param; + parseIndex = paramEndIndex + 1; + } + + //call main program API handler + callback(apiReturn, this); + } +} + +void ScriptClient::closeConnection() +{ + *sc_data = ""; + // Close the connection + delay(1); + flush(); + stop(); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.h new file mode 100644 index 0000000..9fc2e1e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/ScriptClient.h @@ -0,0 +1,21 @@ +#ifndef SCRIPT_CLIENT_H +#define SCRIPT_CLIENT_H +#include +#include +#include "APIReturn.h" + +class ScriptClient; +//Format for API handler is void YourAPIHandler(APIReturn *apiReturn, ScriptClient *client) { ... } +typedef void (*APICallback)(APIReturn *, ScriptClient *); + +class ScriptClient : public WiFiClient +{ +public: + void checkClientAPI(const char *route, APICallback callback); + +private: + void scanAPI(const char *route, APICallback callback); + void closeConnection(); +}; + +#endif \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.cpp new file mode 100644 index 0000000..ac7f355 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.cpp @@ -0,0 +1,84 @@ +/** +* Author: James Brown 2018 +* Crawls a JSON looking for tags +* Saves any allocation +* +* TODO: Move all JSON handling to this class +* - pass a char* so terminators can be inserted and have all the value pairs stay within the original data, which is on stack +**/ + +#include "TagReader.h" +#include +#include + +using namespace std; + +typedef enum STATE_DEF +{ + KEY, + DELIMITER, + VALUE, + DEREFERENCE, + END_VALUE +} READ_STATE; + +TagReader::TagReader() +{ + _length = 0; +} + +const char* TagReader::getTag(const string *JSON_Str, const char *value) +{ + //first determine if the tag exists in the file + size_t index = JSON_Str->find(value); + if (index == string::npos) //safe scan + { + return NULL; + } + + //parse for the end value + READ_STATE read_state = KEY; + READ_STATE old_state; + const char *value_ptr = NULL; + _length = 0; + + while (index < JSON_Str->length() && read_state != END_VALUE) + { + const char c = (*JSON_Str).at(index); + + switch (read_state) + { + case KEY: + if (c == '\"' || c == ':') read_state = DELIMITER; + break; + case DELIMITER: + if (c != '\"' && c != ':') { read_state = VALUE; index--; } + break; + case VALUE: + if (value_ptr == NULL) value_ptr = (const char*)(JSON_Str->c_str() + index); + if (c == '\"') + { + read_state = END_VALUE; + } + else + { + _length++; + } + break; + case DEREFERENCE: + read_state = old_state; + break; + case END_VALUE: + return value_ptr; + } + + if (c == '\\') + { + old_state = read_state; + read_state = DEREFERENCE; + } + index++; + } + + return value_ptr; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.h new file mode 100644 index 0000000..c81c26e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/TagReader/TagReader.h @@ -0,0 +1,23 @@ +#ifndef WEB3_TAG_READER_H +#define WEB3_TAG_READER_H + +#include +#include + +using namespace std; + +class TagReader +{ +public: + TagReader(); + const char * getTag(const string * JSON_Str, const char * value); + size_t length() { return _length; } + +private: + size_t _length; + +}; + + + +#endif // !WEB3_TAG_READER diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/address.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/address.h new file mode 100644 index 0000000..7c5925e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/address.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2016 Daira Hopwood + * Copyright (c) 2016 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __ADDRESS_H__ +#define __ADDRESS_H__ + +#include +#include +#include +#include "options.h" + +size_t address_prefix_bytes_len(uint32_t address_type); +void address_write_prefix_bytes(uint32_t address_type, uint8_t *out); +bool address_check_prefix(const uint8_t *addr, uint32_t address_type); +#if USE_ETHEREUM +void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id); +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/base58.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/base58.h new file mode 100644 index 0000000..0fa9167 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/base58.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BASE58_H__ +#define __BASE58_H__ + +#include +#include +#include "hasher.h" +#include "options.h" + +extern const char b58digits_ordered[]; +extern const int8_t b58digits_map[]; + +int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize); +int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen); + +// Private +bool b58tobin(void *bin, size_t *binszp, const char *b58); +int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str); +bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz); + +#if USE_GRAPHENE +int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize); +int base58gph_decode_check(const char *str, uint8_t *data, int datalen); +int b58gphcheck(const void *bin, size_t binsz, const char *base58str); +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.c new file mode 100644 index 0000000..20c57d9 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.c @@ -0,0 +1,1102 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * Copyright (c) 2015 Jochen Hoenicke + * Copyright (c) 2016 Alex Beregszaszi + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "bignum.h" +#include "memzero.h" + +/* big number library */ + +/* The structure bignum256 is an array of nine 32-bit values, which + * are digits in base 2^30 representation. I.e. the number + * bignum256 a; + * represents the value + * sum_{i=0}^8 a.val[i] * 2^{30 i}. + * + * The number is *normalized* iff every digit is < 2^30. + * + * As the name suggests, a bignum256 is intended to represent a 256 + * bit number, but it can represent 270 bits. Numbers are usually + * reduced using a prime, either the group order or the field prime. + * The reduction is often partly done by bn_fast_mod, and similarly + * implicitly in bn_multiply. A *partly reduced number* is a + * normalized number between 0 (inclusive) and 2*prime (exclusive). + * + * A partly reduced number can be fully reduced by calling bn_mod. + * Only a fully reduced number is guaranteed to fit in 256 bit. + * + * All functions assume that the prime in question is slightly smaller + * than 2^256. In particular it must be between 2^256-2^224 and + * 2^256 and it must be a prime number. + */ + +inline uint32_t read_be(const uint8_t *data) +{ + return (((uint32_t)data[0]) << 24) | + (((uint32_t)data[1]) << 16) | + (((uint32_t)data[2]) << 8) | + (((uint32_t)data[3])); +} + +inline void write_be(uint8_t *data, uint32_t x) +{ + data[0] = x >> 24; + data[1] = x >> 16; + data[2] = x >> 8; + data[3] = x; +} + +inline uint32_t read_le(const uint8_t *data) +{ + return (((uint32_t)data[3]) << 24) | + (((uint32_t)data[2]) << 16) | + (((uint32_t)data[1]) << 8) | + (((uint32_t)data[0])); +} + +inline void write_le(uint8_t *data, uint32_t x) +{ + data[3] = x >> 24; + data[2] = x >> 16; + data[1] = x >> 8; + data[0] = x; +} + +// convert a raw bigendian 256 bit value into a normalized bignum. +// out_number is partly reduced (since it fits in 256 bit). +void bn_read_be(const uint8_t *in_number, bignum256 *out_number) +{ + int i; + uint32_t temp = 0; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number % 2^(32i)) >> 30i + // get next limb = (in_number % 2^(32(i+1))) >> 32i + uint32_t limb = read_be(in_number + (7 - i) * 4); + // temp = (in_number % 2^(32(i+1))) << 30i + temp |= limb << (2*i); + // store 30 bits into val[i] + out_number->val[i]= temp & 0x3FFFFFFF; + // prepare temp for next round + temp = limb >> (30 - 2*i); + } + out_number->val[8] = temp; +} + +// convert a normalized bignum to a raw bigendian 256 bit number. +// in_number must be fully reduced. +void bn_write_be(const bignum256 *in_number, uint8_t *out_number) +{ + int i; + uint32_t temp = in_number->val[8]; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number >> 30*(8-i)) + uint32_t limb = in_number->val[7 - i]; + temp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i)); + write_be(out_number + i * 4, temp); + temp = limb; + } +} + +// convert a raw little endian 256 bit value into a normalized bignum. +// out_number is partly reduced (since it fits in 256 bit). +void bn_read_le(const uint8_t *in_number, bignum256 *out_number) +{ + int i; + uint32_t temp = 0; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number % 2^(32i)) >> 30i + // get next limb = (in_number % 2^(32(i+1))) >> 32i + uint32_t limb = read_le(in_number + i * 4); + // temp = (in_number % 2^(32(i+1))) << 30i + temp |= limb << (2*i); + // store 30 bits into val[i] + out_number->val[i]= temp & 0x3FFFFFFF; + // prepare temp for next round + temp = limb >> (30 - 2*i); + } + out_number->val[8] = temp; +} + +// convert a normalized bignum to a raw little endian 256 bit number. +// in_number must be fully reduced. +void bn_write_le(const bignum256 *in_number, uint8_t *out_number) +{ + int i; + uint32_t temp = in_number->val[8]; + for (i = 0; i < 8; i++) { + // invariant: temp = (in_number >> 30*(8-i)) + uint32_t limb = in_number->val[7 - i]; + temp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i)); + write_le(out_number + (7 - i) * 4, temp); + temp = limb; + } +} + +void bn_read_uint32(uint32_t in_number, bignum256 *out_number) +{ + out_number->val[0] = in_number & 0x3FFFFFFF; + out_number->val[1] = in_number >> 30; + out_number->val[2] = 0; + out_number->val[3] = 0; + out_number->val[4] = 0; + out_number->val[5] = 0; + out_number->val[6] = 0; + out_number->val[7] = 0; + out_number->val[8] = 0; +} + +void bn_read_uint64(uint64_t in_number, bignum256 *out_number) +{ + out_number->val[0] = in_number & 0x3FFFFFFF; + out_number->val[1] = (in_number >>= 30) & 0x3FFFFFFF; + out_number->val[2] = in_number >>= 30; + out_number->val[3] = 0; + out_number->val[4] = 0; + out_number->val[5] = 0; + out_number->val[6] = 0; + out_number->val[7] = 0; + out_number->val[8] = 0; +} + +// a must be normalized +int bn_bitcount(const bignum256 *a) +{ + int i; + for (i = 8; i >= 0; i--) { + int tmp = a->val[i]; + if (tmp != 0) { + return i * 30 + (32 - __builtin_clz(tmp)); + } + } + return 0; +} + +#define DIGITS 78 // log10(2 ^ 256) + +unsigned int bn_digitcount(const bignum256 *a) +{ + bignum256 val; + memcpy(&val, a, sizeof(bignum256)); + + unsigned int digits = 1; + + for (unsigned int i = 0; i < DIGITS; i += 3) { + uint32_t limb; + bn_divmod1000(&val, &limb); + + if (limb >= 100) { + digits = i + 3; + } else if (limb >= 10) { + digits = i + 2; + } else if (limb >= 1) { + digits = i + 1; + } + } + + return digits; +} + +// sets a bignum to zero. +void bn_zero(bignum256 *a) +{ + int i; + for (i = 0; i < 9; i++) { + a->val[i] = 0; + } +} + +// sets a bignum to one. +void bn_one(bignum256 *a) +{ + a->val[0] = 1; + a->val[1] = 0; + a->val[2] = 0; + a->val[3] = 0; + a->val[4] = 0; + a->val[5] = 0; + a->val[6] = 0; + a->val[7] = 0; + a->val[8] = 0; +} + +// checks that a bignum is zero. +// a must be normalized +// function is constant time (on some architectures, in particular ARM). +int bn_is_zero(const bignum256 *a) +{ + int i; + uint32_t result = 0; + for (i = 0; i < 9; i++) { + result |= a->val[i]; + } + return !result; +} + +// Check whether a < b +// a and b must be normalized +// function is constant time (on some architectures, in particular ARM). +int bn_is_less(const bignum256 *a, const bignum256 *b) +{ + int i; + uint32_t res1 = 0; + uint32_t res2 = 0; + for (i = 8; i >= 0; i--) { + res1 = (res1 << 1) | (a->val[i] < b->val[i]); + res2 = (res2 << 1) | (a->val[i] > b->val[i]); + } + return res1 > res2; +} + +// Check whether a == b +// a and b must be normalized +// function is constant time (on some architectures, in particular ARM). +int bn_is_equal(const bignum256 *a, const bignum256 *b) { + int i; + uint32_t result = 0; + for (i = 0; i < 9; i++) { + result |= (a->val[i] ^ b->val[i]); + } + return !result; +} + +// Assigns res = cond ? truecase : falsecase +// assumes that cond is either 0 or 1. +// function is constant time. +void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase) +{ + int i; + uint32_t tmask = (uint32_t) -cond; + uint32_t fmask = ~tmask; + + assert (cond == 1 || cond == 0); + for (i = 0; i < 9; i++) { + res->val[i] = (truecase->val[i] & tmask) | + (falsecase->val[i] & fmask); + } +} + +// shift number to the left, i.e multiply it by 2. +// a must be normalized. The result is normalized but not reduced. +void bn_lshift(bignum256 *a) +{ + int i; + for (i = 8; i > 0; i--) { + a->val[i] = ((a->val[i] << 1) & 0x3FFFFFFF) | ((a->val[i - 1] & 0x20000000) >> 29); + } + a->val[0] = (a->val[0] << 1) & 0x3FFFFFFF; +} + +// shift number to the right, i.e divide by 2 while rounding down. +// a must be normalized. The result is normalized. +void bn_rshift(bignum256 *a) +{ + int i; + for (i = 0; i < 8; i++) { + a->val[i] = (a->val[i] >> 1) | ((a->val[i + 1] & 1) << 29); + } + a->val[8] >>= 1; +} + +// sets bit in bignum +void bn_setbit(bignum256 *a, uint8_t bit) +{ + a->val[bit / 30] |= (1u << (bit % 30)); +} + +// clears bit in bignum +void bn_clearbit(bignum256 *a, uint8_t bit) +{ + a->val[bit / 30] &= ~(1u << (bit % 30)); +} + +// tests bit in bignum +uint32_t bn_testbit(bignum256 *a, uint8_t bit) +{ + return a->val[bit / 30] & (1u << (bit % 30)); +} + +// a = b ^ c +void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c) +{ + int i; + for (i = 0; i < 9; i++) { + a->val[i] = b->val[i] ^ c->val[i]; + } +} + +// multiply x by 1/2 modulo prime. +// it computes x = (x & 1) ? (x + prime) >> 1 : x >> 1. +// assumes x is normalized. +// if x was partly reduced, it is also partly reduced on exit. +// function is constant time. +void bn_mult_half(bignum256 * x, const bignum256 *prime) +{ + int j; + uint32_t xodd = -(x->val[0] & 1); + // compute x = x/2 mod prime + // if x is odd compute (x+prime)/2 + uint32_t tmp1 = (x->val[0] + (prime->val[0] & xodd)) >> 1; + for (j = 0; j < 8; j++) { + uint32_t tmp2 = (x->val[j+1] + (prime->val[j+1] & xodd)); + tmp1 += (tmp2 & 1) << 29; + x->val[j] = tmp1 & 0x3fffffff; + tmp1 >>= 30; + tmp1 += tmp2 >> 1; + } + x->val[8] = tmp1; +} + +// multiply x by k modulo prime. +// assumes x is normalized, 0 <= k <= 4. +// guarantees x is partly reduced. +void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime) +{ + int j; + for (j = 0; j < 9; j++) { + x->val[j] = k * x->val[j]; + } + bn_fast_mod(x, prime); +} + +// compute x = x mod prime by computing x >= prime ? x - prime : x. +// assumes x partly reduced, guarantees x fully reduced. +void bn_mod(bignum256 *x, const bignum256 *prime) +{ + const int flag = bn_is_less(x, prime); // x < prime + bignum256 temp; + bn_subtract(x, prime, &temp); // temp = x - prime + bn_cmov(x, flag, x, &temp); +} + +// auxiliary function for multiplication. +// compute k * x as a 540 bit number in base 2^30 (normalized). +// assumes that k and x are normalized. +void bn_multiply_long(const bignum256 *k, const bignum256 *x, uint32_t res[18]) +{ + int i, j; + uint64_t temp = 0; + + // compute lower half of long multiplication + for (i = 0; i < 9; i++) + { + for (j = 0; j <= i; j++) { + // no overflow, since 9*2^60 < 2^64 + temp += k->val[j] * (uint64_t)x->val[i - j]; + } + res[i] = temp & 0x3FFFFFFFu; + temp >>= 30; + } + // compute upper half + for (; i < 17; i++) + { + for (j = i - 8; j < 9 ; j++) { + // no overflow, since 9*2^60 < 2^64 + temp += k->val[j] * (uint64_t)x->val[i - j]; + } + res[i] = temp & 0x3FFFFFFFu; + temp >>= 30; + } + res[17] = temp; +} + +// auxiliary function for multiplication. +// reduces res modulo prime. +// assumes res normalized, res < 2^(30(i-7)) * 2 * prime +// guarantees res normalized, res < 2^(30(i-8)) * 2 * prime +void bn_multiply_reduce_step(uint32_t res[18], const bignum256 *prime, uint32_t i) { + // let k = i-8. + // on entry: + // 0 <= res < 2^(30k + 31) * prime + // estimate coef = (res / prime / 2^30k) + // by coef = res / 2^(30k + 256) rounded down + // 0 <= coef < 2^31 + // subtract (coef * 2^(30k) * prime) from res + // note that we unrolled the first iteration + uint32_t j; + uint32_t coef = (res[i] >> 16) + (res[i + 1] << 14); + uint64_t temp = 0x2000000000000000ull + res[i - 8] - prime->val[0] * (uint64_t)coef; + assert (coef < 0x80000000u); + res[i - 8] = temp & 0x3FFFFFFF; + for (j = 1; j < 9; j++) { + temp >>= 30; + // Note: coeff * prime->val[j] <= (2^31-1) * (2^30-1) + // Hence, this addition will not underflow. + temp += 0x1FFFFFFF80000000ull + res[i - 8 + j] - prime->val[j] * (uint64_t)coef; + res[i - 8 + j] = temp & 0x3FFFFFFF; + // 0 <= temp < 2^61 + 2^30 + } + temp >>= 30; + temp += 0x1FFFFFFF80000000ull + res[i - 8 + j]; + res[i - 8 + j] = temp & 0x3FFFFFFF; + // we rely on the fact that prime > 2^256 - 2^224 + // res = oldres - coef*2^(30k) * prime; + // and + // coef * 2^(30k + 256) <= oldres < (coef+1) * 2^(30k + 256) + // Hence, 0 <= res < 2^30k (2^256 + coef * (2^256 - prime)) + // < 2^30k (2^256 + 2^31 * 2^224) + // < 2^30k (2 * prime) +} + + +// auxiliary function for multiplication. +// reduces x = res modulo prime. +// assumes res normalized, res < 2^270 * 2 * prime +// guarantees x partly reduced, i.e., x < 2 * prime +void bn_multiply_reduce(bignum256 *x, uint32_t res[18], const bignum256 *prime) +{ + int i; + // res = k * x is a normalized number (every limb < 2^30) + // 0 <= res < 2^270 * 2 * prime. + for (i = 16; i >= 8; i--) { + bn_multiply_reduce_step(res, prime, i); + assert(res[i + 1] == 0); + } + // store the result + for (i = 0; i < 9; i++) { + x->val[i] = res[i]; + } +} + +// Compute x := k * x (mod prime) +// both inputs must be smaller than 180 * prime. +// result is partly reduced (0 <= x < 2 * prime) +// This only works for primes between 2^256-2^224 and 2^256. +void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime) +{ + uint32_t res[18] = {0}; + bn_multiply_long(k, x, res); + bn_multiply_reduce(x, res, prime); + memzero(res, sizeof(res)); +} + +// partly reduce x modulo prime +// input x does not have to be normalized. +// x can be any number that fits. +// prime must be between (2^256 - 2^224) and 2^256 +// result is partly reduced, smaller than 2*prime +void bn_fast_mod(bignum256 *x, const bignum256 *prime) +{ + int j; + uint32_t coef; + uint64_t temp; + + coef = x->val[8] >> 16; + // substract (coef * prime) from x + // note that we unrolled the first iteration + temp = 0x2000000000000000ull + x->val[0] - prime->val[0] * (uint64_t)coef; + x->val[0] = temp & 0x3FFFFFFF; + for (j = 1; j < 9; j++) { + temp >>= 30; + temp += 0x1FFFFFFF80000000ull + x->val[j] - prime->val[j] * (uint64_t)coef; + x->val[j] = temp & 0x3FFFFFFF; + } +} + +// square root of x = x^((p+1)/4) +// http://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus +// assumes x is normalized but not necessarily reduced. +// guarantees x is reduced +void bn_sqrt(bignum256 *x, const bignum256 *prime) +{ + // this method compute x^1/2 = x^(prime+1)/4 + uint32_t i, j, limb; + bignum256 res, p; + bn_one(&res); + // compute p = (prime+1)/4 + memcpy(&p, prime, sizeof(bignum256)); + bn_addi(&p, 1); + bn_rshift(&p); + bn_rshift(&p); + for (i = 0; i < 9; i++) { + // invariants: + // x = old(x)^(2^(i*30)) + // res = old(x)^(p % 2^(i*30)) + // get the i-th limb of prime - 2 + limb = p.val[i]; + for (j = 0; j < 30; j++) { + // invariants: + // x = old(x)^(2^(i*30+j)) + // res = old(x)^(p % 2^(i*30+j)) + // limb = (p % 2^(i*30+30)) / 2^(i*30+j) + if (i == 8 && limb == 0) break; + if (limb & 1) { + bn_multiply(x, &res, prime); + } + limb >>= 1; + bn_multiply(x, x, prime); + } + } + bn_mod(&res, prime); + memcpy(x, &res, sizeof(bignum256)); + memzero(&res, sizeof(res)); + memzero(&p, sizeof(p)); +} + +#if ! USE_INVERSE_FAST + +// in field G_prime, small but slow +void bn_inverse(bignum256 *x, const bignum256 *prime) +{ + // this method compute x^-1 = x^(prime-2) + uint32_t i, j, limb; + bignum256 res; + bn_one(&res); + for (i = 0; i < 9; i++) { + // invariants: + // x = old(x)^(2^(i*30)) + // res = old(x)^((prime-2) % 2^(i*30)) + // get the i-th limb of prime - 2 + limb = prime->val[i]; + // this is not enough in general but fine for secp256k1 & nist256p1 because prime->val[0] > 1 + if (i == 0) limb -= 2; + for (j = 0; j < 30; j++) { + // invariants: + // x = old(x)^(2^(i*30+j)) + // res = old(x)^((prime-2) % 2^(i*30+j)) + // limb = ((prime-2) % 2^(i*30+30)) / 2^(i*30+j) + // early abort when only zero bits follow + if (i == 8 && limb == 0) break; + if (limb & 1) { + bn_multiply(x, &res, prime); + } + limb >>= 1; + bn_multiply(x, x, prime); + } + } + bn_mod(&res, prime); + memcpy(x, &res, sizeof(bignum256)); +} + +#else + +// in field G_prime, big and complicated but fast +// the input must not be 0 mod prime. +// the result is smaller than prime +void bn_inverse(bignum256 *x, const bignum256 *prime) +{ + int i, j, k, cmp; + struct combo { + uint32_t a[9]; + int len1; + } us, vr, *odd, *even; + uint32_t pp[8]; + uint32_t temp32; + uint64_t temp; + + // The algorithm is based on Schroeppel et. al. "Almost Modular Inverse" + // algorithm. We keep four values u,v,r,s in the combo registers + // us and vr. us stores u in the first len1 limbs (little endian) + // and s in the last 9-len1 limbs (big endian). vr stores v and r. + // This is because both u*s and v*r are guaranteed to fit in 8 limbs, so + // their components are guaranteed to fit in 9. During the algorithm, + // the length of u and v shrinks while r and s grow. + // u,v,r,s correspond to F,G,B,C in Schroeppel's algorithm. + + // reduce x modulo prime. This is necessary as it has to fit in 8 limbs. + bn_fast_mod(x, prime); + bn_mod(x, prime); + // convert x and prime to 8x32 bit limb form + temp32 = prime->val[0]; + for (i = 0; i < 8; i++) { + temp32 |= prime->val[i + 1] << (30-2*i); + us.a[i] = pp[i] = temp32; + temp32 = prime->val[i + 1] >> (2+2*i); + } + temp32 = x->val[0]; + for (i = 0; i < 8; i++) { + temp32 |= x->val[i + 1] << (30-2*i); + vr.a[i] = temp32; + temp32 = x->val[i + 1] >> (2+2*i); + } + us.len1 = 8; + vr.len1 = 8; + // set s = 1 and r = 0 + us.a[8] = 1; + vr.a[8] = 0; + // set k = 0. + k = 0; + + // only one of the numbers u,v can be even at any time. We + // let even point to that number and odd to the other. + // Initially the prime u is guaranteed to be odd. + odd = &us; + even = &vr; + + // u = prime, v = x + // r = 0 , s = 1 + // k = 0 + for (;;) { + // invariants: + // let u = limbs us.a[0..u.len1-1] in little endian, + // let s = limbs us.a[u.len..8] in big endian, + // let v = limbs vr.a[0..u.len1-1] in little endian, + // let r = limbs vr.a[u.len..8] in big endian, + // r,s >= 0 ; u,v >= 1 + // x*-r = u*2^k mod prime + // x*s = v*2^k mod prime + // u*s + v*r = prime + // floor(log2(u)) + floor(log2(v)) + k <= 510 + // max(u,v) <= 2^k (*) see comment at end of loop + // gcd(u,v) = 1 + // {odd,even} = {&us, &vr} + // odd->a[0] and odd->a[8] are odd + // even->a[0] or even->a[8] is even + // + // first u/v are large and r/s small + // later u/v are small and r/s large + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + + // adjust length of even. + while (even->a[even->len1 - 1] == 0) { + even->len1--; + // if input was 0, return. + // This simple check prevents crashing with stack underflow + // or worse undesired behaviour for illegal input. + if (even->len1 < 0) + return; + } + + // reduce even->a while it is even + while (even->a[0] == 0) { + // shift right first part of even by a limb + // and shift left second part of even by a limb. + for (i = 0; i < 8; i++) { + even->a[i] = even->a[i+1]; + } + even->a[i] = 0; + even->len1--; + k += 32; + } + // count up to 32 zero bits of even->a. + j = 0; + while ((even->a[0] & (1u << j)) == 0) { + j++; + } + if (j > 0) { + // shift first part of even right by j bits. + for (i = 0; i + 1 < even->len1; i++) { + even->a[i] = (even->a[i] >> j) | (even->a[i + 1] << (32 - j)); + } + even->a[i] = (even->a[i] >> j); + if (even->a[i] == 0) { + even->len1--; + } else { + i++; + } + + // shift second part of even left by j bits. + for (; i < 8; i++) { + even->a[i] = (even->a[i] << j) | (even->a[i + 1] >> (32 - j)); + } + even->a[i] = (even->a[i] << j); + // add j bits to k. + k += j; + } + // invariant is reestablished. + // now both a[0] are odd. + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + assert(even->a[0] & 1); + assert((even->a[8] & 1) == 0); + + // cmp > 0 if us.a[0..len1-1] > vr.a[0..len1-1], + // cmp = 0 if equal, < 0 if less. + cmp = us.len1 - vr.len1; + if (cmp == 0) { + i = us.len1 - 1; + while (i >= 0 && us.a[i] == vr.a[i]) i--; + // both are equal to 1 and we are done. + if (i == -1) + break; + cmp = us.a[i] > vr.a[i] ? 1 : -1; + } + if (cmp > 0) { + even = &us; + odd = &vr; + } else { + even = &vr; + odd = &us; + } + + // now even > odd. + + // even->a[0..len1-1] = (even->a[0..len1-1] - odd->a[0..len1-1]); + temp = 1; + for (i = 0; i < odd->len1; i++) { + temp += 0xFFFFFFFFull + even->a[i] - odd->a[i]; + even->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + for (; i < even->len1; i++) { + temp += 0xFFFFFFFFull + even->a[i]; + even->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + // odd->a[len1..8] = (odd->b[len1..8] + even->b[len1..8]); + temp = 0; + for (i = 8; i >= even->len1; i--) { + temp += (uint64_t) odd->a[i] + even->a[i]; + odd->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + for (; i >= odd->len1; i--) { + temp += (uint64_t) odd->a[i]; + odd->a[i] = temp & 0xFFFFFFFF; + temp >>= 32; + } + // note that + // if u > v: + // u'2^k = (u - v) 2^k = x(-r) - xs = x(-(r+s)) = x(-r') mod prime + // u's' + v'r' = (u-v)s + v(r+s) = us + vr + // if u < v: + // v'2^k = (v - u) 2^k = xs - x(-r) = x(s+r) = xs' mod prime + // u's' + v'r' = u(s+r) + (v-u)r = us + vr + + // even->a[0] is difference between two odd numbers, hence even. + // odd->a[8] is sum of even and odd number, hence odd. + assert(odd->a[0] & 1); + assert(odd->a[8] & 1); + assert((even->a[0] & 1) == 0); + + // The invariants are (almost) reestablished. + // The invariant max(u,v) <= 2^k can be invalidated at this point, + // because odd->a[len1..8] was changed. We only have + // + // odd->a[len1..8] <= 2^{k+1} + // + // Since even->a[0] is even, k will be incremented at the beginning + // of the next loop while odd->a[len1..8] remains unchanged. + // So after that, odd->a[len1..8] <= 2^k will hold again. + } + // In the last iteration we had u = v and gcd(u,v) = 1. + // Hence, u=1, v=1, s+r = prime, k <= 510, 2^k > max(s,r) >= prime/2 + // This implies 0 <= s < prime and 255 <= k <= 510. + // + // The invariants also give us x*s = 2^k mod prime, + // hence s = 2^k * x^-1 mod prime. + // We need to compute s/2^k mod prime. + + // First we compute inverse = -prime^-1 mod 2^32, which we need later. + // We use the Explicit Quadratic Modular inverse algorithm. + // http://arxiv.org/pdf/1209.6626.pdf + // a^-1 = (2-a) * PROD_i (1 + (a - 1)^(2^i)) mod 2^32 + // the product will converge quickly, because (a-1)^(2^i) will be + // zero mod 2^32 after at most five iterations. + // We want to compute -prime^-1 so we start with (pp[0]-2). + assert(pp[0] & 1); + uint32_t amone = pp[0]-1; + uint32_t inverse = pp[0] - 2; + while (amone) { + amone *= amone; + inverse *= (amone + 1); + } + + while (k >= 32) { + // compute s / 2^32 modulo prime. + // Idea: compute factor, such that + // s + factor*prime mod 2^32 == 0 + // i.e. factor = s * -1/prime mod 2^32. + // Then compute s + factor*prime and shift right by 32 bits. + uint32_t factor = (inverse * us.a[8]) & 0xffffffff; + temp = us.a[8] + (uint64_t) pp[0] * factor; + assert((temp & 0xffffffff) == 0); + temp >>= 32; + for (i = 0; i < 7; i++) { + temp += us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor; + us.a[8-i] = temp & 0xffffffff; + temp >>= 32; + } + us.a[8-i] = temp & 0xffffffff; + k -= 32; + } + if (k > 0) { + // compute s / 2^k modulo prime. + // Same idea: compute factor, such that + // s + factor*prime mod 2^k == 0 + // i.e. factor = s * -1/prime mod 2^k. + // Then compute s + factor*prime and shift right by k bits. + uint32_t mask = (1u << k) - 1; + uint32_t factor = (inverse * us.a[8]) & mask; + temp = (us.a[8] + (uint64_t) pp[0] * factor) >> k; + assert(((us.a[8] + pp[0] * factor) & mask) == 0); + for (i = 0; i < 7; i++) { + temp += (us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor) << (32 - k); + us.a[8-i] = temp & 0xffffffff; + temp >>= 32; + } + us.a[8-i] = temp & 0xffffffff; + } + + // convert s to bignum style + temp32 = 0; + for (i = 0; i < 8; i++) { + x->val[i] = ((us.a[8-i] << (2 * i)) & 0x3FFFFFFFu) | temp32; + temp32 = us.a[8-i] >> (30 - 2 * i); + } + x->val[i] = temp32; + + // let's wipe all temp buffers + memzero(pp, sizeof(pp)); + memzero(&us, sizeof(us)); + memzero(&vr, sizeof(vr)); +} +#endif + +void bn_normalize(bignum256 *a) { + bn_addi(a, 0); +} + +// add two numbers a = a + b +// assumes that a, b are normalized +// guarantees that a is normalized +void bn_add(bignum256 *a, const bignum256 *b) +{ + int i; + uint32_t tmp = 0; + for (i = 0; i < 9; i++) { + tmp += a->val[i] + b->val[i]; + a->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } +} + +void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime) +{ + int i; + for (i = 0; i < 9; i++) { + a->val[i] += b->val[i]; + } + bn_fast_mod(a, prime); +} + +void bn_addi(bignum256 *a, uint32_t b) { + int i; + uint32_t tmp = b; + for (i = 0; i < 9; i++) { + tmp += a->val[i]; + a->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } +} + +void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime) { + assert (b <= prime->val[0]); + // the possible underflow will be taken care of when adding the prime + a->val[0] -= b; + bn_add(a, prime); +} + +// res = a - b mod prime. More exactly res = a + (2*prime - b). +// b must be a partly reduced number +// result is normalized but not reduced. +void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime) +{ + int i; + uint32_t temp = 1; + for (i = 0; i < 9; i++) { + temp += 0x3FFFFFFF + a->val[i] + 2u * prime->val[i] - b->val[i]; + res->val[i] = temp & 0x3FFFFFFF; + temp >>= 30; + } +} + +// res = a - b ; a > b +void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res) +{ + int i; + uint32_t tmp = 1; + for (i = 0; i < 9; i++) { + tmp += 0x3FFFFFFF + a->val[i] - b->val[i]; + res->val[i] = tmp & 0x3FFFFFFF; + tmp >>= 30; + } +} + +// a / 58 = a (+r) +void bn_divmod58(bignum256 *a, uint32_t *r) +{ + int i; + uint32_t rem, tmp; + rem = a->val[8] % 58; + a->val[8] /= 58; + for (i = 7; i >= 0; i--) { + // invariants: + // rem = old(a) >> 30(i+1) % 58 + // a[i+1..8] = old(a[i+1..8])/58 + // a[0..i] = old(a[0..i]) + // 2^30 == 18512790*58 + 4 + tmp = rem * 4 + a->val[i]; + // set a[i] = (rem * 2^30 + a[i])/58 + // = rem * 18512790 + (rem * 4 + a[i])/58 + a->val[i] = rem * 18512790 + (tmp / 58); + // set rem = (rem * 2^30 + a[i]) mod 58 + // = (rem * 4 + a[i]) mod 58 + rem = tmp % 58; + } + *r = rem; +} + +// a / 1000 = a (+r) +void bn_divmod1000(bignum256 *a, uint32_t *r) +{ + int i; + uint32_t rem, tmp; + rem = a->val[8] % 1000; + a->val[8] /= 1000; + for (i = 7; i >= 0; i--) { + // invariants: + // rem = old(a) >> 30(i+1) % 1000 + // a[i+1..8] = old(a[i+1..8])/1000 + // a[0..i] = old(a[0..i]) + // 2^30 == 1073741*1000 + 824 + tmp = rem * 824 + a->val[i]; + // set a[i] = (rem * 2^30 + a[i])/1000 + // = rem * 1073741 + (rem * 824 + a[i])/1000 + a->val[i] = rem * 1073741 + (tmp / 1000); + // set rem = (rem * 2^30 + a[i]) mod 1000 + // = (rem * 824 + a[i]) mod 1000 + rem = tmp % 1000; + } + *r = rem; +} + +size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen) +{ + size_t prefixlen = prefix ? strlen(prefix) : 0; + size_t suffixlen = suffix ? strlen(suffix) : 0; + + /* add prefix to beginning of out buffer */ + if (prefixlen) { + memcpy(out, prefix, prefixlen); + } + /* add suffix to end of out buffer */ + if (suffixlen) { + memcpy(&out[outlen - suffixlen - 1], suffix, suffixlen); + } + /* nul terminate (even if suffix = NULL) */ + out[outlen - 1] = '\0'; + + /* fill number between prefix and suffix (between start and end) */ + char *start = &out[prefixlen], *end = &out[outlen - suffixlen - 1]; + char *str = end; + +#define BN_FORMAT_PUSH_CHECKED(c) \ + do { \ + if (str == start) return 0; \ + *--str = (c); \ + } while (0) + +#define BN_FORMAT_PUSH(n) \ + do { \ + if (exponent < 0) { \ + exponent++; \ + } else { \ + if ((n) > 0 || trailing || str != end || decimals <= 1) { \ + BN_FORMAT_PUSH_CHECKED('0' + (n)); \ + } \ + if (decimals > 0 && decimals-- == 1) { \ + BN_FORMAT_PUSH_CHECKED('.'); \ + } \ + } \ + } while (0) + + bignum256 val; + memcpy(&val, amnt, sizeof(bignum256)); + + if (bn_is_zero(&val)) { + exponent = 0; + } + + for (; exponent > 0; exponent--) { + BN_FORMAT_PUSH(0); + } + + unsigned int digits = bn_digitcount(&val); + for (unsigned int i = 0; i < digits / 3; i++) { + uint32_t limb; + bn_divmod1000(&val, &limb); + + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + BN_FORMAT_PUSH(limb % 10); + } + + if (digits % 3 != 0) { + uint32_t limb; + bn_divmod1000(&val, &limb); + + switch (digits % 3) { + case 2: + BN_FORMAT_PUSH(limb % 10); + limb /= 10; + //-fallthrough + + case 1: + BN_FORMAT_PUSH(limb % 10); + break; + } + } + + while (decimals > 0 || str[0] == '\0' || str[0] == '.') { + BN_FORMAT_PUSH(0); + } + + /* finally move number to &out[prefixlen] to close the gap between + * prefix and str. len is length of number + suffix + traling 0 + */ + size_t len = &out[outlen] - str; + memmove(&out[prefixlen], str, len); + + /* return length of number including prefix and suffix without trailing 0 */ + return prefixlen + len - 1; +} + +#if USE_BN_PRINT +void bn_print(const bignum256 *a) +{ + printf("%04x", a->val[8] & 0x0000FFFF); + printf("%08x", (a->val[7] << 2) | ((a->val[6] & 0x30000000) >> 28)); + printf("%07x", a->val[6] & 0x0FFFFFFF); + printf("%08x", (a->val[5] << 2) | ((a->val[4] & 0x30000000) >> 28)); + printf("%07x", a->val[4] & 0x0FFFFFFF); + printf("%08x", (a->val[3] << 2) | ((a->val[2] & 0x30000000) >> 28)); + printf("%07x", a->val[2] & 0x0FFFFFFF); + printf("%08x", (a->val[1] << 2) | ((a->val[0] & 0x30000000) >> 28)); + printf("%07x", a->val[0] & 0x0FFFFFFF); +} + +void bn_print_raw(const bignum256 *a) +{ + int i; + for (i = 0; i <= 8; i++) { + printf("0x%08x, ", a->val[i]); + } +} +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.h new file mode 100644 index 0000000..f96cad6 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bignum.h @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * Copyright (c) 2016 Alex Beregszaszi + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ + +#include +#include +#include +#include "options.h" + +// bignum256 are 256 bits stored as 8*30 bit + 1*16 bit +// val[0] are lowest 30 bits, val[8] highest 16 bits +typedef struct { + uint32_t val[9]; +} bignum256; + +// read 4 big endian bytes into uint32 +uint32_t read_be(const uint8_t *data); + +// write 4 big endian bytes +void write_be(uint8_t *data, uint32_t x); + +// read 4 little endian bytes into uint32 +uint32_t read_le(const uint8_t *data); + +// write 4 little endian bytes +void write_le(uint8_t *data, uint32_t x); + +void bn_read_be(const uint8_t *in_number, bignum256 *out_number); + +void bn_write_be(const bignum256 *in_number, uint8_t *out_number); + +void bn_read_le(const uint8_t *in_number, bignum256 *out_number); + +void bn_write_le(const bignum256 *in_number, uint8_t *out_number); + +void bn_read_uint32(uint32_t in_number, bignum256 *out_number); + +void bn_read_uint64(uint64_t in_number, bignum256 *out_number); + +static inline uint32_t bn_write_uint32(const bignum256 *in_number) +{ + return in_number->val[0] | (in_number->val[1] << 30); +} + +static inline uint64_t bn_write_uint64(const bignum256 *in_number) +{ + uint64_t tmp; + tmp = in_number->val[2]; + tmp <<= 30; + tmp |= in_number->val[1]; + tmp <<= 30; + tmp |= in_number->val[0]; + return tmp; +} + +// copies number a to b +static inline void bn_copy(const bignum256 *a, bignum256 *b) { + *b = *a; +} + +int bn_bitcount(const bignum256 *a); + +unsigned int bn_digitcount(const bignum256 *a); + +void bn_zero(bignum256 *a); + +int bn_is_zero(const bignum256 *a); + +void bn_one(bignum256 *a); + +static inline int bn_is_even(const bignum256 *a) { + return (a->val[0] & 1) == 0; +} + +static inline int bn_is_odd(const bignum256 *a) { + return (a->val[0] & 1) == 1; +} + +int bn_is_less(const bignum256 *a, const bignum256 *b); + +int bn_is_equal(const bignum256 *a, const bignum256 *b); + +void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase); + +void bn_lshift(bignum256 *a); + +void bn_rshift(bignum256 *a); + +void bn_setbit(bignum256 *a, uint8_t bit); + +void bn_clearbit(bignum256 *a, uint8_t bit); + +uint32_t bn_testbit(bignum256 *a, uint8_t bit); + +void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c); + +void bn_mult_half(bignum256 *x, const bignum256 *prime); + +void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime); + +void bn_mod(bignum256 *x, const bignum256 *prime); + +void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime); + +void bn_fast_mod(bignum256 *x, const bignum256 *prime); + +void bn_sqrt(bignum256 *x, const bignum256 *prime); + +void bn_inverse(bignum256 *x, const bignum256 *prime); + +void bn_normalize(bignum256 *a); + +void bn_add(bignum256 *a, const bignum256 *b); + +void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime); + +void bn_addi(bignum256 *a, uint32_t b); + +void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime); + +void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime); + +void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res); + +void bn_divmod58(bignum256 *a, uint32_t *r); + +void bn_divmod1000(bignum256 *a, uint32_t *r); + +size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen); + +static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen) +{ + bignum256 amnt; + bn_read_uint64(amount, &amnt); + + return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, outlen); +} + +#if USE_BN_PRINT +void bn_print(const bignum256 *a); +void bn_print_raw(const bignum256 *a); +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bip32.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bip32.h new file mode 100644 index 0000000..12e9175 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/bip32.h @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __BIP32_H__ +#define __BIP32_H__ + +#include +#include +#include +#include "ecdsa.h" +#include "options.h" + +typedef struct { + const char *bip32_name; // string for generating BIP32 xprv from seed + const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519 + + HasherType hasher_base58; + HasherType hasher_sign; + HasherType hasher_pubkey; + HasherType hasher_script; +} curve_info; + +typedef struct { + uint32_t depth; + uint32_t child_num; + uint8_t chain_code[32]; + + uint8_t private_key[32]; + uint8_t private_key_extension[32]; + + uint8_t public_key[33]; + const curve_info *curve; +} HDNode; + +int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out); + +int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out); + +int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out); + +#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000)) + +int hdnode_private_ckd(HDNode *inout, uint32_t i); + +#if USE_CARDANO +int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); +int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out); +#endif + +int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code); + +int hdnode_public_ckd(HDNode *inout, uint32_t i); + +void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat); + +#if USE_BIP32_CACHE +int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint); +#endif + +uint32_t hdnode_fingerprint(HDNode *node); + +void hdnode_fill_public_key(HDNode *node); + +int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash); + +int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); + +int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size); + +int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); + +int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize); + +int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint); + +void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw); +void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize); + +const curve_info *get_curve_by_name(const char *curve_name); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.c new file mode 100644 index 0000000..972339b --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.c @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2016 Jochen Hoenicke + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "curves.h" + +const char SECP256K1_NAME[] = "secp256k1"; +const char SECP256K1_DECRED_NAME[] = "secp256k1-decred"; +const char SECP256K1_GROESTL_NAME[] = "secp256k1-groestl"; +const char SECP256K1_SMART_NAME[] = "secp256k1-smart"; +const char NIST256P1_NAME[] = "nist256p1"; +const char ED25519_NAME[] = "ed25519"; +const char ED25519_CARDANO_NAME[] = "ed25519 cardano seed"; +const char ED25519_SHA3_NAME[] = "ed25519-sha3"; +#if USE_KECCAK +const char ED25519_KECCAK_NAME[] = "ed25519-keccak"; +#endif +const char CURVE25519_NAME[] = "curve25519"; diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.h new file mode 100644 index 0000000..34b796e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/curves.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2016 Jochen Hoenicke + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CURVES_H__ +#define __CURVES_H__ + +#include "options.h" + +extern const char SECP256K1_NAME[]; +extern const char SECP256K1_DECRED_NAME[]; +extern const char SECP256K1_GROESTL_NAME[]; +extern const char SECP256K1_SMART_NAME[]; +extern const char NIST256P1_NAME[]; +extern const char ED25519_NAME[]; +extern const char ED25519_CARDANO_NAME[]; +extern const char ED25519_SHA3_NAME[]; +#if USE_KECCAK +extern const char ED25519_KECCAK_NAME[]; +#endif +extern const char CURVE25519_NAME[]; + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.c new file mode 100644 index 0000000..96985b9 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.c @@ -0,0 +1,1066 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * Copyright (c) 2015 Jochen Hoenicke + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "bignum.h" +#include "rand.h" +#include "hmac.h" +#include "ecdsa.h" +#include "secp256k1.h" +#include "rfc6979.h" +#include "memzero.h" + +// Set cp2 = cp1 +void point_copy(const curve_point *cp1, curve_point *cp2) +{ + *cp2 = *cp1; +} + +// cp2 = cp1 + cp2 +void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2) +{ + bignum256 lambda, inv, xr, yr; + + if (point_is_infinity(cp1)) { + return; + } + if (point_is_infinity(cp2)) { + point_copy(cp1, cp2); + return; + } + if (point_is_equal(cp1, cp2)) { + point_double(curve, cp2); + return; + } + if (point_is_negative_of(cp1, cp2)) { + point_set_infinity(cp2); + return; + } + + bn_subtractmod(&(cp2->x), &(cp1->x), &inv, &curve->prime); + bn_inverse(&inv, &curve->prime); + bn_subtractmod(&(cp2->y), &(cp1->y), &lambda, &curve->prime); + bn_multiply(&inv, &lambda, &curve->prime); + + // xr = lambda^2 - x1 - x2 + xr = lambda; + bn_multiply(&xr, &xr, &curve->prime); + yr = cp1->x; + bn_addmod(&yr, &(cp2->x), &curve->prime); + bn_subtractmod(&xr, &yr, &xr, &curve->prime); + bn_fast_mod(&xr, &curve->prime); + bn_mod(&xr, &curve->prime); + + // yr = lambda (x1 - xr) - y1 + bn_subtractmod(&(cp1->x), &xr, &yr, &curve->prime); + bn_multiply(&lambda, &yr, &curve->prime); + bn_subtractmod(&yr, &(cp1->y), &yr, &curve->prime); + bn_fast_mod(&yr, &curve->prime); + bn_mod(&yr, &curve->prime); + + cp2->x = xr; + cp2->y = yr; +} + +// cp = cp + cp +void point_double(const ecdsa_curve *curve, curve_point *cp) +{ + bignum256 lambda, xr, yr; + + if (point_is_infinity(cp)) { + return; + } + if (bn_is_zero(&(cp->y))) { + point_set_infinity(cp); + return; + } + + // lambda = (3 x^2 + a) / (2 y) + lambda = cp->y; + bn_mult_k(&lambda, 2, &curve->prime); + bn_inverse(&lambda, &curve->prime); + + xr = cp->x; + bn_multiply(&xr, &xr, &curve->prime); + bn_mult_k(&xr, 3, &curve->prime); + bn_subi(&xr, -curve->a, &curve->prime); + bn_multiply(&xr, &lambda, &curve->prime); + + // xr = lambda^2 - 2*x + xr = lambda; + bn_multiply(&xr, &xr, &curve->prime); + yr = cp->x; + bn_lshift(&yr); + bn_subtractmod(&xr, &yr, &xr, &curve->prime); + bn_fast_mod(&xr, &curve->prime); + bn_mod(&xr, &curve->prime); + + // yr = lambda (x - xr) - y + bn_subtractmod(&(cp->x), &xr, &yr, &curve->prime); + bn_multiply(&lambda, &yr, &curve->prime); + bn_subtractmod(&yr, &(cp->y), &yr, &curve->prime); + bn_fast_mod(&yr, &curve->prime); + bn_mod(&yr, &curve->prime); + + cp->x = xr; + cp->y = yr; +} + +// set point to internal representation of point at infinity +void point_set_infinity(curve_point *p) +{ + bn_zero(&(p->x)); + bn_zero(&(p->y)); +} + +// return true iff p represent point at infinity +// both coords are zero in internal representation +int point_is_infinity(const curve_point *p) +{ + return bn_is_zero(&(p->x)) && bn_is_zero(&(p->y)); +} + +// return true iff both points are equal +int point_is_equal(const curve_point *p, const curve_point *q) +{ + return bn_is_equal(&(p->x), &(q->x)) && bn_is_equal(&(p->y), &(q->y)); +} + +// returns true iff p == -q +// expects p and q be valid points on curve other than point at infinity +int point_is_negative_of(const curve_point *p, const curve_point *q) +{ + // if P == (x, y), then -P would be (x, -y) on this curve + if (!bn_is_equal(&(p->x), &(q->x))) { + return 0; + } + + // we shouldn't hit this for a valid point + if (bn_is_zero(&(p->y))) { + return 0; + } + + return !bn_is_equal(&(p->y), &(q->y)); +} + +// Negate a (modulo prime) if cond is 0xffffffff, keep it if cond is 0. +// The timing of this function does not depend on cond. +void conditional_negate(uint32_t cond, bignum256 *a, const bignum256 *prime) +{ + int j; + uint32_t tmp = 1; + assert(a->val[8] < 0x20000); + for (j = 0; j < 8; j++) { + tmp += 0x3fffffff + 2*prime->val[j] - a->val[j]; + a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); + tmp >>= 30; + } + tmp += 0x3fffffff + 2*prime->val[j] - a->val[j]; + a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond); + assert(a->val[8] < 0x20000); +} + +typedef struct jacobian_curve_point { + bignum256 x, y, z; +} jacobian_curve_point; + +// generate random K for signing/side-channel noise +static void generate_k_random(bignum256 *k, const bignum256 *prime) { + do { + int i; + for (i = 0; i < 8; i++) { + k->val[i] = random32() & 0x3FFFFFFF; + } + k->val[8] = random32() & 0xFFFF; + // check that k is in range and not zero. + } while (bn_is_zero(k) || !bn_is_less(k, prime)); +} + +void curve_to_jacobian(const curve_point *p, jacobian_curve_point *jp, const bignum256 *prime) { + // randomize z coordinate + generate_k_random(&jp->z, prime); + + jp->x = jp->z; + bn_multiply(&jp->z, &jp->x, prime); + // x = z^2 + jp->y = jp->x; + bn_multiply(&jp->z, &jp->y, prime); + // y = z^3 + + bn_multiply(&p->x, &jp->x, prime); + bn_multiply(&p->y, &jp->y, prime); +} + +void jacobian_to_curve(const jacobian_curve_point *jp, curve_point *p, const bignum256 *prime) { + p->y = jp->z; + bn_inverse(&p->y, prime); + // p->y = z^-1 + p->x = p->y; + bn_multiply(&p->x, &p->x, prime); + // p->x = z^-2 + bn_multiply(&p->x, &p->y, prime); + // p->y = z^-3 + bn_multiply(&jp->x, &p->x, prime); + // p->x = jp->x * z^-2 + bn_multiply(&jp->y, &p->y, prime); + // p->y = jp->y * z^-3 + bn_mod(&p->x, prime); + bn_mod(&p->y, prime); +} + +void point_jacobian_add(const curve_point *p1, jacobian_curve_point *p2, const ecdsa_curve *curve) { + bignum256 r, h, r2; + bignum256 hcby, hsqx; + bignum256 xz, yz, az; + int is_doubling; + const bignum256 *prime = &curve->prime; + int a = curve->a; + + assert (-3 <= a && a <= 0); + + /* First we bring p1 to the same denominator: + * x1' := x1 * z2^2 + * y1' := y1 * z2^3 + */ + /* + * lambda = ((y1' - y2)/z2^3) / ((x1' - x2)/z2^2) + * = (y1' - y2) / (x1' - x2) z2 + * x3/z3^2 = lambda^2 - (x1' + x2)/z2^2 + * y3/z3^3 = 1/2 lambda * (2x3/z3^2 - (x1' + x2)/z2^2) + (y1'+y2)/z2^3 + * + * For the special case x1=x2, y1=y2 (doubling) we have + * lambda = 3/2 ((x2/z2^2)^2 + a) / (y2/z2^3) + * = 3/2 (x2^2 + a*z2^4) / y2*z2) + * + * to get rid of fraction we write lambda as + * lambda = r / (h*z2) + * with r = is_doubling ? 3/2 x2^2 + az2^4 : (y1 - y2) + * h = is_doubling ? y1+y2 : (x1 - x2) + * + * With z3 = h*z2 (the denominator of lambda) + * we get x3 = lambda^2*z3^2 - (x1' + x2)/z2^2*z3^2 + * = r^2 - h^2 * (x1' + x2) + * and y3 = 1/2 r * (2x3 - h^2*(x1' + x2)) + h^3*(y1' + y2) + */ + + /* h = x1 - x2 + * r = y1 - y2 + * x3 = r^2 - h^3 - 2*h^2*x2 + * y3 = r*(h^2*x2 - x3) - h^3*y2 + * z3 = h*z2 + */ + + xz = p2->z; + bn_multiply(&xz, &xz, prime); // xz = z2^2 + yz = p2->z; + bn_multiply(&xz, &yz, prime); // yz = z2^3 + + if (a != 0) { + az = xz; + bn_multiply(&az, &az, prime); // az = z2^4 + bn_mult_k(&az, -a, prime); // az = -az2^4 + } + + bn_multiply(&p1->x, &xz, prime); // xz = x1' = x1*z2^2; + h = xz; + bn_subtractmod(&h, &p2->x, &h, prime); + bn_fast_mod(&h, prime); + // h = x1' - x2; + + bn_add(&xz, &p2->x); + // xz = x1' + x2 + + // check for h == 0 % prime. Note that h never normalizes to + // zero, since h = x1' + 2*prime - x2 > 0 and a positive + // multiple of prime is always normalized to prime by + // bn_fast_mod. + is_doubling = bn_is_equal(&h, prime); + + bn_multiply(&p1->y, &yz, prime); // yz = y1' = y1*z2^3; + bn_subtractmod(&yz, &p2->y, &r, prime); + // r = y1' - y2; + + bn_add(&yz, &p2->y); + // yz = y1' + y2 + + r2 = p2->x; + bn_multiply(&r2, &r2, prime); + bn_mult_k(&r2, 3, prime); + + if (a != 0) { + // subtract -a z2^4, i.e, add a z2^4 + bn_subtractmod(&r2, &az, &r2, prime); + } + bn_cmov(&r, is_doubling, &r2, &r); + bn_cmov(&h, is_doubling, &yz, &h); + + + // hsqx = h^2 + hsqx = h; + bn_multiply(&hsqx, &hsqx, prime); + + // hcby = h^3 + hcby = h; + bn_multiply(&hsqx, &hcby, prime); + + // hsqx = h^2 * (x1 + x2) + bn_multiply(&xz, &hsqx, prime); + + // hcby = h^3 * (y1 + y2) + bn_multiply(&yz, &hcby, prime); + + // z3 = h*z2 + bn_multiply(&h, &p2->z, prime); + + // x3 = r^2 - h^2 (x1 + x2) + p2->x = r; + bn_multiply(&p2->x, &p2->x, prime); + bn_subtractmod(&p2->x, &hsqx, &p2->x, prime); + bn_fast_mod(&p2->x, prime); + + // y3 = 1/2 (r*(h^2 (x1 + x2) - 2x3) - h^3 (y1 + y2)) + bn_subtractmod(&hsqx, &p2->x, &p2->y, prime); + bn_subtractmod(&p2->y, &p2->x, &p2->y, prime); + bn_multiply(&r, &p2->y, prime); + bn_subtractmod(&p2->y, &hcby, &p2->y, prime); + bn_mult_half(&p2->y, prime); + bn_fast_mod(&p2->y, prime); +} + +void point_jacobian_double(jacobian_curve_point *p, const ecdsa_curve *curve) { + bignum256 az4, m, msq, ysq, xysq; + const bignum256 *prime = &curve->prime; + + assert (-3 <= curve->a && curve->a <= 0); + /* usual algorithm: + * + * lambda = (3((x/z^2)^2 + a) / 2y/z^3) = (3x^2 + az^4)/2yz + * x3/z3^2 = lambda^2 - 2x/z^2 + * y3/z3^3 = lambda * (x/z^2 - x3/z3^2) - y/z^3 + * + * to get rid of fraction we set + * m = (3 x^2 + az^4) / 2 + * Hence, + * lambda = m / yz = m / z3 + * + * With z3 = yz (the denominator of lambda) + * we get x3 = lambda^2*z3^2 - 2*x/z^2*z3^2 + * = m^2 - 2*xy^2 + * and y3 = (lambda * (x/z^2 - x3/z3^2) - y/z^3) * z3^3 + * = m * (xy^2 - x3) - y^4 + */ + + /* m = (3*x^2 + a z^4) / 2 + * x3 = m^2 - 2*xy^2 + * y3 = m*(xy^2 - x3) - 8y^4 + * z3 = y*z + */ + + m = p->x; + bn_multiply(&m, &m, prime); + bn_mult_k(&m, 3, prime); + + az4 = p->z; + bn_multiply(&az4, &az4, prime); + bn_multiply(&az4, &az4, prime); + bn_mult_k(&az4, -curve->a, prime); + bn_subtractmod(&m, &az4, &m, prime); + bn_mult_half(&m, prime); + + // msq = m^2 + msq = m; + bn_multiply(&msq, &msq, prime); + // ysq = y^2 + ysq = p->y; + bn_multiply(&ysq, &ysq, prime); + // xysq = xy^2 + xysq = p->x; + bn_multiply(&ysq, &xysq, prime); + + // z3 = yz + bn_multiply(&p->y, &p->z, prime); + + // x3 = m^2 - 2*xy^2 + p->x = xysq; + bn_lshift(&p->x); + bn_fast_mod(&p->x, prime); + bn_subtractmod(&msq, &p->x, &p->x, prime); + bn_fast_mod(&p->x, prime); + + // y3 = m*(xy^2 - x3) - y^4 + bn_subtractmod(&xysq, &p->x, &p->y, prime); + bn_multiply(&m, &p->y, prime); + bn_multiply(&ysq, &ysq, prime); + bn_subtractmod(&p->y, &ysq, &p->y, prime); + bn_fast_mod(&p->y, prime); +} + +// res = k * p +void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res) +{ + // this algorithm is loosely based on + // Katsuyuki Okeya and Tsuyoshi Takagi, The Width-w NAF Method Provides + // Small Memory and Fast Elliptic Scalar Multiplications Secure against + // Side Channel Attacks. + assert (bn_is_less(k, &curve->order)); + + int i, j; + static CONFIDENTIAL bignum256 a; + uint32_t *aptr; + uint32_t abits; + int ashift; + uint32_t is_even = (k->val[0] & 1) - 1; + uint32_t bits, sign, nsign; + static CONFIDENTIAL jacobian_curve_point jres; + curve_point pmult[8]; + const bignum256 *prime = &curve->prime; + + // is_even = 0xffffffff if k is even, 0 otherwise. + + // add 2^256. + // make number odd: subtract curve->order if even + uint32_t tmp = 1; + uint32_t is_non_zero = 0; + for (j = 0; j < 8; j++) { + is_non_zero |= k->val[j]; + tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); + a.val[j] = tmp & 0x3fffffff; + tmp >>= 30; + } + is_non_zero |= k->val[j]; + a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); + assert((a.val[0] & 1) != 0); + + // special case 0*p: just return zero. We don't care about constant time. + if (!is_non_zero) { + point_set_infinity(res); + return; + } + + // Now a = k + 2^256 (mod curve->order) and a is odd. + // + // The idea is to bring the new a into the form. + // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. + // a[0] is odd, since a is odd. If a[i] would be even, we can + // add 1 to it and subtract 16 from a[i-1]. Afterwards, + // a[64] = 1, which is the 2^256 that we added before. + // + // Since k = a - 2^256 (mod curve->order), we can compute + // k*p = sum_{i=0..63} a[i] 16^i * p + // + // We compute |a[i]| * p in advance for all possible + // values of |a[i]| * p. pmult[i] = (2*i+1) * p + // We compute p, 3*p, ..., 15*p and store it in the table pmult. + // store p^2 temporarily in pmult[7] + pmult[7] = *p; + point_double(curve, &pmult[7]); + // compute 3*p, etc by repeatedly adding p^2. + pmult[0] = *p; + for (i = 1; i < 8; i++) { + pmult[i] = pmult[7]; + point_add(curve, &pmult[i-1], &pmult[i]); + } + + // now compute res = sum_{i=0..63} a[i] * 16^i * p step by step, + // starting with i = 63. + // initialize jres = |a[63]| * p. + // Note that a[i] = a>>(4*i) & 0xf if (a&0x10) != 0 + // and - (16 - (a>>(4*i) & 0xf)) otherwise. We can compute this as + // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 + // since a is odd. + aptr = &a.val[8]; + abits = *aptr; + ashift = 12; + bits = abits >> ashift; + sign = (bits >> 4) - 1; + bits ^= sign; + bits &= 15; + curve_to_jacobian(&pmult[bits>>1], &jres, prime); + for (i = 62; i >= 0; i--) { + // sign = sign(a[i+1]) (0xffffffff for negative, 0 for positive) + // invariant jres = (-1)^sign sum_{j=i+1..63} (a[j] * 16^{j-i-1} * p) + // abits >> (ashift - 4) = lowbits(a >> (i*4)) + + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + point_jacobian_double(&jres, curve); + + // get lowest 5 bits of a >> (i*4). + ashift -= 4; + if (ashift < 0) { + // the condition only depends on the iteration number and + // leaks no private information to a side-channel. + bits = abits << (-ashift); + abits = *(--aptr); + ashift += 30; + bits |= abits >> ashift; + } else { + bits = abits >> ashift; + } + bits &= 31; + nsign = (bits >> 4) - 1; + bits ^= nsign; + bits &= 15; + + // negate last result to make signs of this round and the + // last round equal. + conditional_negate(sign ^ nsign, &jres.z, prime); + + // add odd factor + point_jacobian_add(&pmult[bits >> 1], &jres, curve); + sign = nsign; + } + conditional_negate(sign, &jres.z, prime); + jacobian_to_curve(&jres, res, prime); + memzero(&a, sizeof(a)); + memzero(&jres, sizeof(jres)); +} + +#if USE_PRECOMPUTED_CP + +// res = k * G +// k must be a normalized number with 0 <= k < curve->order +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res) +{ + assert (bn_is_less(k, &curve->order)); + + int i, j; + static CONFIDENTIAL bignum256 a; + uint32_t is_even = (k->val[0] & 1) - 1; + uint32_t lowbits; + static CONFIDENTIAL jacobian_curve_point jres; + const bignum256 *prime = &curve->prime; + + // is_even = 0xffffffff if k is even, 0 otherwise. + + // add 2^256. + // make number odd: subtract curve->order if even + uint32_t tmp = 1; + uint32_t is_non_zero = 0; + for (j = 0; j < 8; j++) { + is_non_zero |= k->val[j]; + tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even); + a.val[j] = tmp & 0x3fffffff; + tmp >>= 30; + } + is_non_zero |= k->val[j]; + a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even); + assert((a.val[0] & 1) != 0); + + // special case 0*G: just return zero. We don't care about constant time. + if (!is_non_zero) { + point_set_infinity(res); + return; + } + + // Now a = k + 2^256 (mod curve->order) and a is odd. + // + // The idea is to bring the new a into the form. + // sum_{i=0..64} a[i] 16^i, where |a[i]| < 16 and a[i] is odd. + // a[0] is odd, since a is odd. If a[i] would be even, we can + // add 1 to it and subtract 16 from a[i-1]. Afterwards, + // a[64] = 1, which is the 2^256 that we added before. + // + // Since k = a - 2^256 (mod curve->order), we can compute + // k*G = sum_{i=0..63} a[i] 16^i * G + // + // We have a big table curve->cp that stores all possible + // values of |a[i]| 16^i * G. + // curve->cp[i][j] = (2*j+1) * 16^i * G + + // now compute res = sum_{i=0..63} a[i] * 16^i * G step by step. + // initial res = |a[0]| * G. Note that a[0] = a & 0xf if (a&0x10) != 0 + // and - (16 - (a & 0xf)) otherwise. We can compute this as + // ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1 + // since a is odd. + lowbits = a.val[0] & ((1 << 5) - 1); + lowbits ^= (lowbits >> 4) - 1; + lowbits &= 15; + curve_to_jacobian(&curve->cp[0][lowbits >> 1], &jres, prime); + for (i = 1; i < 64; i ++) { + // invariant res = sign(a[i-1]) sum_{j=0..i-1} (a[j] * 16^j * G) + + // shift a by 4 places. + for (j = 0; j < 8; j++) { + a.val[j] = (a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << 26); + } + a.val[j] >>= 4; + // a = old(a)>>(4*i) + // a is even iff sign(a[i-1]) = -1 + + lowbits = a.val[0] & ((1 << 5) - 1); + lowbits ^= (lowbits >> 4) - 1; + lowbits &= 15; + // negate last result to make signs of this round and the + // last round equal. + conditional_negate((lowbits & 1) - 1, &jres.y, prime); + + // add odd factor + point_jacobian_add(&curve->cp[i][lowbits >> 1], &jres, curve); + } + conditional_negate(((a.val[0] >> 4) & 1) - 1, &jres.y, prime); + jacobian_to_curve(&jres, res, prime); + memzero(&a, sizeof(a)); + memzero(&jres, sizeof(jres)); +} + +#else + +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res) +{ + point_multiply(curve, k, &curve->G, res); +} + +#endif + +int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key) +{ + curve_point point; + if (!ecdsa_read_pubkey(curve, pub_key, &point)) { + return 1; + } + + bignum256 k; + bn_read_be(priv_key, &k); + point_multiply(curve, &k, &point, &point); + memzero(&k, sizeof(k)); + + session_key[0] = 0x04; + bn_write_be(&point.x, session_key + 1); + bn_write_be(&point.y, session_key + 33); + memzero(&point, sizeof(point)); + + return 0; +} + +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { + uint8_t bx[2*32]; + uint8_t buf[32 + 1 + 2*32]; + + memcpy(bx, priv_key, 32); + memcpy(bx+32, hash, 32); + + memset(state->v, 1, sizeof(state->v)); + memset(state->k, 0, sizeof(state->k)); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x01; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + + memzero(bx, sizeof(bx)); + memzero(buf, sizeof(buf)); +} + +// generate next number from deterministic random number generator +void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) +{ + uint8_t buf[32 + 1]; + + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(rnd, buf, 32); + memzero(buf, sizeof(buf)); +} + +// generate K in a deterministic way, according to RFC6979 +// http://tools.ietf.org/html/rfc6979 +void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) +{ + uint8_t buf[32]; + generate_rfc6979(buf, state); + bn_read_be(buf, k); + memzero(buf, sizeof(buf)); +} + +// uses secp256k1 curve +// priv_key is a 32 byte big endian stored number +// sig is 64 bytes long array for the signature +// digest is 32 bytes of digest +// is_canonical is an optional function that checks if the signature +// conforms to additional coin-specific rules. +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) +{ + int i; + curve_point R; + bignum256 k, z, randk; + bignum256 *s = &R.y; + uint8_t by; // signature recovery byte + +#if USE_RFC6979 + rfc6979_state rng; + init_rfc6979(priv_key, digest, &rng); +#endif + + bn_read_be(digest, &z); + + for (i = 0; i < 10000; i++) { + +#if USE_RFC6979 + // generate K deterministically + generate_k_rfc6979(&k, &rng); + // if k is too big or too small, we don't like it + if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) { + continue; + } +#else + // generate random number k + generate_k_random(&k, &curve->order); +#endif + + // compute k*G + scalar_multiply(curve, &k, &R); + by = R.y.val[0] & 1; + // r = (rx mod n) + if (!bn_is_less(&R.x, &curve->order)) { + bn_subtract(&R.x, &curve->order, &R.x); + by |= 2; + } + // if r is zero, we retry + if (bn_is_zero(&R.x)) { + continue; + } + + // randomize operations to counter side-channel attacks + generate_k_random(&randk, &curve->order); + bn_multiply(&randk, &k, &curve->order); // k*rand + bn_inverse(&k, &curve->order); // (k*rand)^-1 + bn_read_be(priv_key, s); // priv + bn_multiply(&R.x, s, &curve->order); // R.x*priv + bn_add(s, &z); // R.x*priv + z + bn_multiply(&k, s, &curve->order); // (k*rand)^-1 (R.x*priv + z) + bn_multiply(&randk, s, &curve->order); // k^-1 (R.x*priv + z) + bn_mod(s, &curve->order); + // if s is zero, we retry + if (bn_is_zero(s)) { + continue; + } + + // if S > order/2 => S = -S + if (bn_is_less(&curve->order_half, s)) { + bn_subtract(&curve->order, s, s); + by ^= 1; + } + // we are done, R.x and s is the result signature + bn_write_be(&R.x, sig); + bn_write_be(s, sig + 32); + + // check if the signature is acceptable or retry + if (is_canonical && !is_canonical(by, sig)) { + continue; + } + + if (pby) { + *pby = by; + } + + memzero(&k, sizeof(k)); + memzero(&randk, sizeof(randk)); +#if USE_RFC6979 + memzero(&rng, sizeof(rng)); +#endif + return 0; + } + + // Too many retries without a valid signature + // -> fail with an error + memzero(&k, sizeof(k)); + memzero(&randk, sizeof(randk)); +#if USE_RFC6979 + memzero(&rng, sizeof(rng)); +#endif + return -1; +} + +void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key) +{ + curve_point R; + bignum256 k; + + bn_read_be(priv_key, &k); + // compute k*G + scalar_multiply(curve, &k, &R); + pub_key[0] = 0x02 | (R.y.val[0] & 0x01); + bn_write_be(&R.x, pub_key + 1); + memzero(&R, sizeof(R)); + memzero(&k, sizeof(k)); +} + +void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key) +{ + curve_point R; + bignum256 k; + + bn_read_be(priv_key, &k); + // compute k*G + scalar_multiply(curve, &k, &R); + pub_key[0] = 0x04; + bn_write_be(&R.x, pub_key + 1); + bn_write_be(&R.y, pub_key + 33); + memzero(&R, sizeof(R)); + memzero(&k, sizeof(k)); +} + +int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed) +{ + curve_point pub; + + if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { + return 0; + } + + uncompressed[0] = 4; + bn_write_be(&pub.x, uncompressed + 1); + bn_write_be(&pub.y, uncompressed + 33); + + return 1; +} + +void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y) +{ + // y^2 = x^3 + a*x + b + memcpy(y, x, sizeof(bignum256)); // y is x + bn_multiply(x, y, &curve->prime); // y is x^2 + bn_subi(y, -curve->a, &curve->prime); // y is x^2 + a + bn_multiply(x, y, &curve->prime); // y is x^3 + ax + bn_add(y, &curve->b); // y is x^3 + ax + b + bn_sqrt(y, &curve->prime); // y = sqrt(y) + if ((odd & 0x01) != (y->val[0] & 1)) { + bn_subtract(&curve->prime, y, y); // y = -y + } +} + +int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub) +{ + if (!curve) { + curve = &secp256k1; + } + if (pub_key[0] == 0x04) { + bn_read_be(pub_key + 1, &(pub->x)); + bn_read_be(pub_key + 33, &(pub->y)); + return ecdsa_validate_pubkey(curve, pub); + } + if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords + bn_read_be(pub_key + 1, &(pub->x)); + uncompress_coords(curve, pub_key[0], &(pub->x), &(pub->y)); + return ecdsa_validate_pubkey(curve, pub); + } + // error + return 0; +} + +// Verifies that: +// - pub is not the point at infinity. +// - pub->x and pub->y are in range [0,p-1]. +// - pub is on the curve. + +int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub) +{ + bignum256 y_2, x3_ax_b; + + if (point_is_infinity(pub)) { + return 0; + } + + if (!bn_is_less(&(pub->x), &curve->prime) || !bn_is_less(&(pub->y), &curve->prime)) { + return 0; + } + + memcpy(&y_2, &(pub->y), sizeof(bignum256)); + memcpy(&x3_ax_b, &(pub->x), sizeof(bignum256)); + + // y^2 + bn_multiply(&(pub->y), &y_2, &curve->prime); + bn_mod(&y_2, &curve->prime); + + // x^3 + ax + b + bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^2 + bn_subi(&x3_ax_b, -curve->a, &curve->prime); // x^2 + a + bn_multiply(&(pub->x), &x3_ax_b, &curve->prime); // x^3 + ax + bn_addmod(&x3_ax_b, &curve->b, &curve->prime); // x^3 + ax + b + bn_mod(&x3_ax_b, &curve->prime); + + if (!bn_is_equal(&x3_ax_b, &y_2)) { + return 0; + } + + return 1; +} + +// Compute public key from signature and recovery id. +// returns 0 if the key is successfully recovered +int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid) +{ + bignum256 r, s, e; + curve_point cp, cp2; + + // read r and s + bn_read_be(sig, &r); + bn_read_be(sig + 32, &s); + if (!bn_is_less(&r, &curve->order) || bn_is_zero(&r)) { + return 1; + } + if (!bn_is_less(&s, &curve->order) || bn_is_zero(&s)) { + return 1; + } + // cp = R = k * G (k is secret nonce when signing) + memcpy(&cp.x, &r, sizeof(bignum256)); + if (recid & 2) { + bn_add(&cp.x, &curve->order); + if (!bn_is_less(&cp.x, &curve->prime)) { + return 1; + } + } + // compute y from x + uncompress_coords(curve, recid & 1, &cp.x, &cp.y); + if (!ecdsa_validate_pubkey(curve, &cp)) { + return 1; + } + // e = -digest + bn_read_be(digest, &e); + bn_subtractmod(&curve->order, &e, &e, &curve->order); + bn_fast_mod(&e, &curve->order); + bn_mod(&e, &curve->order); + // r := r^-1 + bn_inverse(&r, &curve->order); + // cp := s * R = s * k *G + point_multiply(curve, &s, &cp, &cp); + // cp2 := -digest * G + scalar_multiply(curve, &e, &cp2); + // cp := (s * k - digest) * G = (r*priv) * G = r * Pub + point_add(curve, &cp2, &cp); + // cp := r^{-1} * r * Pub = Pub + point_multiply(curve, &r, &cp, &cp); + pub_key[0] = 0x04; + bn_write_be(&cp.x, pub_key + 1); + bn_write_be(&cp.y, pub_key + 33); + return 0; +} + +// returns 0 if verification succeeded +int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest) +{ + curve_point pub, res; + bignum256 r, s, z; + + if (!ecdsa_read_pubkey(curve, pub_key, &pub)) { + return 1; + } + + bn_read_be(sig, &r); + bn_read_be(sig + 32, &s); + + bn_read_be(digest, &z); + + if (bn_is_zero(&r) || bn_is_zero(&s) || + (!bn_is_less(&r, &curve->order)) || + (!bn_is_less(&s, &curve->order))) return 2; + + bn_inverse(&s, &curve->order); // s^-1 + bn_multiply(&s, &z, &curve->order); // z*s^-1 + bn_mod(&z, &curve->order); + bn_multiply(&r, &s, &curve->order); // r*s^-1 + bn_mod(&s, &curve->order); + + int result = 0; + if (bn_is_zero(&z)) { + // our message hashes to zero + // I don't expect this to happen any time soon + result = 3; + } else { + scalar_multiply(curve, &z, &res); + } + + if (result == 0) { + // both pub and res can be infinity, can have y = 0 OR can be equal -> false negative + point_multiply(curve, &s, &pub, &pub); + point_add(curve, &pub, &res); + bn_mod(&(res.x), &curve->order); + // signature does not match + if (!bn_is_equal(&res.x, &r)) { + result = 5; + } + } + + memzero(&pub, sizeof(pub)); + memzero(&res, sizeof(res)); + memzero(&r, sizeof(r)); + memzero(&s, sizeof(s)); + memzero(&z, sizeof(z)); + + // all OK + return result; +} + +int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der) +{ + int i; + uint8_t *p = der, *len, *len1, *len2; + *p = 0x30; p++; // sequence + *p = 0x00; len = p; p++; // len(sequence) + + *p = 0x02; p++; // integer + *p = 0x00; len1 = p; p++; // len(integer) + + // process R + i = 0; + while (sig[i] == 0 && i < 32) { i++; } // skip leading zeroes + if (sig[i] >= 0x80) { // put zero in output if MSB set + *p = 0x00; p++; *len1 = *len1 + 1; + } + while (i < 32) { // copy bytes to output + *p = sig[i]; p++; *len1 = *len1 + 1; i++; + } + + *p = 0x02; p++; // integer + *p = 0x00; len2 = p; p++; // len(integer) + + // process S + i = 32; + while (sig[i] == 0 && i < 64) { i++; } // skip leading zeroes + if (sig[i] >= 0x80) { // put zero in output if MSB set + *p = 0x00; p++; *len2 = *len2 + 1; + } + while (i < 64) { // copy bytes to output + *p = sig[i]; p++; *len2 = *len2 + 1; i++; + } + + *len = *len1 + *len2 + 4; + return *len + 2; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.h new file mode 100644 index 0000000..3f558d3 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ecdsa.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __ECDSA_H__ +#define __ECDSA_H__ + +#include +#include "options.h" +#include "bignum.h" +#include "hasher.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +// curve point x and y +typedef struct { + bignum256 x, y; +} curve_point; + +typedef struct { + + bignum256 prime; // prime order of the finite field + curve_point G; // initial curve point + bignum256 order; // order of G + bignum256 order_half; // order of G divided by 2 + int a; // coefficient 'a' of the elliptic curve + bignum256 b; // coefficient 'b' of the elliptic curve + +#if USE_PRECOMPUTED_CP + const curve_point cp[64][8]; +#endif + +} ecdsa_curve; + +// 4 byte prefix + 40 byte data (segwit) +// 1 byte prefix + 64 byte data (cashaddr) +#define MAX_ADDR_RAW_SIZE 65 +// bottle neck is cashaddr +// segwit is at most 90 characters plus NUL separator +// cashaddr: human readable prefix + 1 separator + 104 data + 8 checksum + 1 NUL +// we choose 130 as maximum (including NUL character) +#define MAX_ADDR_SIZE 130 +// 4 byte prefix + 32 byte privkey + 1 byte compressed marker +#define MAX_WIF_RAW_SIZE (4 + 32 + 1) +// (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL. +#define MAX_WIF_SIZE (57) + +void point_copy(const curve_point *cp1, curve_point *cp2); +void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2); +void point_double(const ecdsa_curve *curve, curve_point *cp); +void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res); +void point_set_infinity(curve_point *p); +int point_is_infinity(const curve_point *p); +int point_is_equal(const curve_point *p, const curve_point *q); +int point_is_negative_of(const curve_point *p, const curve_point *q); +void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res); +int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key); +void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y); +int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed); + +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); +void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); + +int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub); +int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub); +int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest); +int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid); +int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hasher.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hasher.h new file mode 100644 index 0000000..bfb5918 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hasher.h @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2017 Saleem Rashid + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __HASHER_H__ +#define __HASHER_H__ + +#include +#include + +#include "sha2.h" +#include "sha3.h" + +#define HASHER_DIGEST_LENGTH 32 + +typedef enum { + HASHER_SHA2, + HASHER_SHA2D, + HASHER_SHA2_RIPEMD, + + HASHER_SHA3, +#if USE_KECCAK + HASHER_SHA3K, +#endif +} HasherType; + +typedef struct { + HasherType type; + + union { + SHA256_CTX sha2; // for HASHER_SHA2{,D} + SHA3_CTX sha3; // for HASHER_SHA3{,K} + } ctx; +} Hasher; + +void hasher_Init(Hasher *hasher, HasherType type); +void hasher_Reset(Hasher *hasher); +void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length); +void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]); + +void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.c new file mode 100644 index 0000000..04448c8 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.c @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "hmac.h" +#include "options.h" +#include "memzero.h" + +void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen) +{ + static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH]; + memset(i_key_pad, 0, SHA256_BLOCK_LENGTH); + if (keylen > SHA256_BLOCK_LENGTH) { + sha256_Raw(key, keylen, i_key_pad); + } else { + memcpy(i_key_pad, key, keylen); + } + for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) { + hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; + i_key_pad[i] ^= 0x36; + } + sha256_Init(&(hctx->ctx)); + sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH); + memzero(i_key_pad, sizeof(i_key_pad)); +} + +void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen) +{ + sha256_Update(&(hctx->ctx), msg, msglen); +} + +void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) +{ + sha256_Final(&(hctx->ctx), hmac); + sha256_Init(&(hctx->ctx)); + sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH); + sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH); + sha256_Final(&(hctx->ctx), hmac); + memzero(hctx, sizeof(HMAC_SHA256_CTX)); +} + +void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) +{ + static CONFIDENTIAL HMAC_SHA256_CTX hctx; + hmac_sha256_Init(&hctx, key, keylen); + hmac_sha256_Update(&hctx, msg, msglen); + hmac_sha256_Final(&hctx, hmac); +} + +void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest) +{ + static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH/sizeof(uint32_t)]; + + memzero(key_pad, sizeof(key_pad)); + if (keylen > SHA256_BLOCK_LENGTH) { + static CONFIDENTIAL SHA256_CTX context; + sha256_Init(&context); + sha256_Update(&context, key, keylen); + sha256_Final(&context, (uint8_t*)key_pad); + } else { + memcpy(key_pad, key, keylen); + } + + /* compute o_key_pad and its digest */ + for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { + uint32_t data; +#if BYTE_ORDER == LITTLE_ENDIAN + REVERSE32(key_pad[i], data); +#else + data = key_pad[i]; +#endif + key_pad[i] = data ^ 0x5c5c5c5c; + } + sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest); + + /* convert o_key_pad to i_key_pad and compute its digest */ + for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) { + key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636; + } + sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest); + memzero(key_pad, sizeof(key_pad)); +} + +void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen) +{ + static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH]; + memset(i_key_pad, 0, SHA512_BLOCK_LENGTH); + if (keylen > SHA512_BLOCK_LENGTH) { + sha512_Raw(key, keylen, i_key_pad); + } else { + memcpy(i_key_pad, key, keylen); + } + for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) { + hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c; + i_key_pad[i] ^= 0x36; + } + sha512_Init(&(hctx->ctx)); + sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH); + memzero(i_key_pad, sizeof(i_key_pad)); +} + +void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen) +{ + sha512_Update(&(hctx->ctx), msg, msglen); +} + +void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) +{ + sha512_Final(&(hctx->ctx), hmac); + sha512_Init(&(hctx->ctx)); + sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH); + sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH); + sha512_Final(&(hctx->ctx), hmac); + memzero(hctx, sizeof(HMAC_SHA512_CTX)); +} + +void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac) +{ + HMAC_SHA512_CTX hctx; + hmac_sha512_Init(&hctx, key, keylen); + hmac_sha512_Update(&hctx, msg, msglen); + hmac_sha512_Final(&hctx, hmac); +} + +void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest) +{ + static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; + + memzero(key_pad, sizeof(key_pad)); + if (keylen > SHA512_BLOCK_LENGTH) { + static CONFIDENTIAL SHA512_CTX context; + sha512_Init(&context); + sha512_Update(&context, key, keylen); + sha512_Final(&context, (uint8_t*)key_pad); + } else { + memcpy(key_pad, key, keylen); + } + + /* compute o_key_pad and its digest */ + for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { + uint64_t data; +#if BYTE_ORDER == LITTLE_ENDIAN + REVERSE64(key_pad[i], data); +#else + data = key_pad[i]; +#endif + key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c; + } + sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest); + + /* convert o_key_pad to i_key_pad and compute its digest */ + for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) { + key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636; + } + sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest); + memzero(key_pad, sizeof(key_pad)); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.h new file mode 100644 index 0000000..3cfc0cd --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/hmac.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __HMAC_H__ +#define __HMAC_H__ + +#include +#include "sha2.h" + +typedef struct _HMAC_SHA256_CTX { + uint8_t o_key_pad[SHA256_BLOCK_LENGTH]; + SHA256_CTX ctx; +} HMAC_SHA256_CTX; + +typedef struct _HMAC_SHA512_CTX { + uint8_t o_key_pad[SHA512_BLOCK_LENGTH]; + SHA512_CTX ctx; +} HMAC_SHA512_CTX; + +void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen); +void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen); +void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac); +void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); +void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest); + +void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen); +void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen); +void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac); +void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac); +void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.c new file mode 100644 index 0000000..68fad58 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.c @@ -0,0 +1,6 @@ +#include + +void memzero(void *s, size_t n) +{ + memset(s, 0, n); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.h new file mode 100644 index 0000000..ce51aca --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/memzero.h @@ -0,0 +1,8 @@ +#ifndef __MEMZERO_H__ +#define __MEMZERO_H__ + +#include + +void memzero(void *s, size_t n); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.c new file mode 100644 index 0000000..7cffa5c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.c @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "nist256p1.h" + +const ecdsa_curve nist256p1 = { + /* .prime */ { + /*.val =*/ {0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0, 0x1000, 0x3fffc000, 0xffff} + }, + + /* G */ { + /*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b, 0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b, 0x6b17}}, + /*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da, 0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86, 0x4fe3}} + }, + + /* order */ { + /*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc, 0x3fffffff, 0xfff, 0x3fffc000, 0xffff} + }, + + /* order_half */ { + /*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde, 0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff} + }, + + /* a */ -3, + + /* b */ { + /*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65, 0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6} + } + +#if USE_PRECOMPUTED_CP + , + /* cp */ { +#include "nist256p1.table" + } +#endif +}; + +const curve_info nist256p1_info = { + .bip32_name = "Nist256p1 seed", + .params = &nist256p1, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, +}; diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.h new file mode 100644 index 0000000..a1a767e --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NIST256P1_H__ +#define __NIST256P1_H__ + +#include + +#include "ecdsa.h" +#include "bip32.h" + +extern const ecdsa_curve nist256p1; +extern const curve_info nist256p1_info; + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.table b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.table new file mode 100644 index 0000000..c4fc224 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/nist256p1.table @@ -0,0 +1,1664 @@ + { + /* 1*16^0*G: */ + {{{0x1898c296, 0x1284e517, 0x1eb33a0f, 0x00df604b, 0x2440f277, 0x339b958e, 0x04247f8b, 0x347cb84b, 0x6b17}}, + {{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da, 0x0f9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86, 0x4fe3}}}, + /* 3*16^0*G: */ + {{{0x06e7fd6c, 0x2d05986f, 0x3ada985f, 0x31adc87b, 0x0bf165e6, 0x1fbe5475, 0x30a44c8f, 0x3934698c, 0x5ecb}}, + {{0x227d5032, 0x29e6c49e, 0x04fb83d9, 0x0aac0d8e, 0x24a2ecd8, 0x2c1b3869, 0x0ff7e374, 0x19031266, 0x8734}}}, + /* 5*16^0*G: */ + {{{0x03d033ed, 0x05552837, 0x35be5242, 0x2320bf47, 0x268fdfef, 0x13215821, 0x140d2d78, 0x02de9454, 0x5159}}, + {{0x3da16da4, 0x0742ed13, 0x0d80888d, 0x004bc035, 0x0a79260d, 0x06fcdafe, 0x2727d8ae, 0x1f6a2412, 0xe0c1}}}, + /* 7*16^0*G: */ + {{{0x3187b2a3, 0x0018a1c0, 0x00fef5b3, 0x3e7e2e2a, 0x01fb607e, 0x2cc199f0, 0x37b4625b, 0x0edbe82f, 0x8e53}}, + {{0x01f400b4, 0x15786a1b, 0x3041b21c, 0x31cd8cf2, 0x35900053, 0x1a7e0e9b, 0x318366d0, 0x076f780c, 0x73eb}}}, + /* 9*16^0*G: */ + {{{0x10949ee0, 0x1e7a292e, 0x06df8b3d, 0x02b2e30b, 0x31f8729e, 0x24e35475, 0x30b71878, 0x35edbfb7, 0xea68}}, + {{0x0dd048fa, 0x21688929, 0x0de823fe, 0x1c53faa9, 0x0ea0c84d, 0x052a592a, 0x1fce7870, 0x11325cb2, 0x2a27}}}, + /* 11*16^0*G: */ + {{{0x34bc21d1, 0x0cce474d, 0x15048bf4, 0x1d0bb409, 0x021cda16, 0x20de76c3, 0x34c59063, 0x04ede20e, 0x3ed1}}, + {{0x282a3740, 0x0be3bbf3, 0x29889dae, 0x03413697, 0x34c68a09, 0x210ebe93, 0x0c8a224c, 0x0826b331, 0x9099}}}, + /* 13*16^0*G: */ + {{{0x06072c01, 0x23857675, 0x1ead58a9, 0x0b8a12d9, 0x1ee2fc79, 0x0177cb61, 0x0495a618, 0x20deb82b, 0x177c}}, + {{0x2fc7bfd8, 0x310eef8b, 0x1fb4df39, 0x3b8530e8, 0x0f4e7226, 0x0246b6d0, 0x2a558a24, 0x163353af, 0x63bb}}}, + /* 15*16^0*G: */ + {{{0x259b9d5f, 0x0d9a318f, 0x23a0ef16, 0x00ebe4b7, 0x088265ae, 0x2cde2666, 0x2bae7adf, 0x1371a5c6, 0xf045}}, + {{0x0d034f36, 0x1f967378, 0x1b5fa3f4, 0x0ec8739d, 0x1643e62a, 0x1653947e, 0x22d1f4e6, 0x0fb8d64b, 0xb5b9}}} + }, + { + /* 1*16^1*G: */ + {{{0x21277c6e, 0x17ad1e1f, 0x36ca038a, 0x0a0e4bbf, 0x36315fcd, 0x08718a60, 0x341858b8, 0x1344e29a, 0x76a9}}, + {{0x0b8c5110, 0x3a7775c9, 0x3c78baa0, 0x26680103, 0x1e872085, 0x0286d784, 0x3260e6cb, 0x3f984d07, 0xa985}}}, + /* 3*16^1*G: */ + {{{0x1e4536ca, 0x2fee771a, 0x2201a61a, 0x0ba4a582, 0x30cda11c, 0x39d16f81, 0x139ec8cc, 0x3ec39249, 0x9482}}, + {{0x358cc1c8, 0x3eb618ef, 0x307bfbb1, 0x0f578a55, 0x134e63f6, 0x358e329d, 0x157f91a5, 0x2729d17c, 0x351d}}}, + /* 5*16^1*G: */ + {{{0x15ecff13, 0x26c76b8a, 0x3d0633c4, 0x1d928736, 0x081eeb63, 0x0d69454c, 0x131195b8, 0x2df05eba, 0xb2e1}}, + {{0x32187d44, 0x0ee92626, 0x3dea2e6a, 0x3686a605, 0x1758c387, 0x0e868aab, 0x3ebccf23, 0x1104c4e8, 0xe6c0}}}, + /* 7*16^1*G: */ + {{{0x2ef87286, 0x22eeccd3, 0x02309e43, 0x00fa1f7f, 0x06ee3407, 0x105df72f, 0x36bc2cb3, 0x118b9fc6, 0xb433}}, + {{0x041496d9, 0x2b011fda, 0x22cea4b7, 0x3388201a, 0x292e6f9d, 0x3d39cb05, 0x2b5fe383, 0x15149bb4, 0xa0da}}}, + /* 9*16^1*G: */ + {{{0x19794381, 0x2e61ad6c, 0x2b0c7601, 0x245621d7, 0x167b1918, 0x1ba416d5, 0x1a24cc18, 0x0833934f, 0xa474}}, + {{0x22769c52, 0x25b38e9f, 0x1f6ac786, 0x2970236e, 0x167afff3, 0x37e4d866, 0x1bfe0e73, 0x3ff7def8, 0x2ebb}}}, + /* 11*16^1*G: */ + {{{0x09a5185a, 0x31d11992, 0x35e6f2be, 0x21c2b227, 0x0da3195b, 0x335004ac, 0x091485fe, 0x1e866e74, 0x05ba}}, + {{0x01de3a4e, 0x150f2238, 0x105ae001, 0x018882f2, 0x23d48e76, 0x1e08f893, 0x01896e46, 0x34ad7a0b, 0x30e0}}}, + /* 13*16^1*G: */ + {{{0x399b85fe, 0x2a8e62d7, 0x23a5dfd5, 0x03bfa6ab, 0x03e0b79c, 0x26364602, 0x3e2fd697, 0x1d327437, 0xb29f}}, + {{0x2da604dc, 0x2e990a5d, 0x3f59e80d, 0x3bd8f4c2, 0x17c6d92d, 0x01c4ba5b, 0x29785d5d, 0x16f0e9b0, 0xa3ce}}}, + /* 15*16^1*G: */ + {{{0x07e030ef, 0x1d9d15ba, 0x0d50e962, 0x1acac15f, 0x082b0857, 0x32fc0fc9, 0x1bcf5076, 0x26eaa2e4, 0x9929}}, + {{0x18d9aa9a, 0x3639adf7, 0x34008444, 0x304b1267, 0x0eaa7957, 0x0e04069b, 0x38e18bf3, 0x38f4cccf, 0x5cc2}}} + }, + { + /* 1*16^2*G: */ + {{{0x12d0441b, 0x36cb8d7c, 0x16a564c2, 0x0342dc43, 0x03ed6119, 0x3f454a18, 0x1165987f, 0x3528ec02, 0x34a2}}, + {{0x1e93b146, 0x10939e11, 0x2ddd81db, 0x35d9ae77, 0x377fc0e7, 0x29c411b9, 0x1e3c22bc, 0x3b5a94e8, 0xbeaa}}}, + /* 3*16^2*G: */ + {{{0x3da08424, 0x3392b8ce, 0x0f644a9d, 0x2fedeadd, 0x1d23ed3a, 0x2317fea5, 0x359aa1b5, 0x0281eb70, 0xa98b}}, + {{0x2831800c, 0x184a1e83, 0x0df582d3, 0x0afa02e8, 0x1d132075, 0x067a3238, 0x19b66e53, 0x3191c892, 0x4754}}}, + /* 5*16^2*G: */ + {{{0x083c2d6a, 0x14b5f97a, 0x1bd29b3b, 0x0be46360, 0x1a696dd2, 0x2dade321, 0x1aac5d21, 0x3c027223, 0xa034}}, + {{0x02c30e72, 0x10cdbbcb, 0x2267e7cf, 0x0180d7c5, 0x2ceb06be, 0x36e15173, 0x19c1fb0c, 0x000db2a2, 0xfe1b}}}, + /* 7*16^2*G: */ + {{{0x28be8c78, 0x05a94774, 0x3793e4d7, 0x025b3e0a, 0x22e9a14a, 0x1b8ad025, 0x14401a07, 0x09bfcc67, 0xb522}}, + {{0x11686903, 0x00cd9f29, 0x1b58ff32, 0x27dff239, 0x12851a81, 0x2cd9a5fa, 0x1f540ca1, 0x38327d4e, 0x701e}}}, + /* 9*16^2*G: */ + {{{0x2058b5a4, 0x0103f902, 0x131979b7, 0x11193e1e, 0x0c4713de, 0x233b33f3, 0x205b3d96, 0x221861a3, 0xa3e3}}, + {{0x27113aef, 0x3cc1b643, 0x371a2948, 0x3ba116ed, 0x17e68f3c, 0x239aceba, 0x0d12c384, 0x15e21f7c, 0xcfd4}}}, + /* 11*16^2*G: */ + {{{0x04a08314, 0x017d7b24, 0x1c7dff7a, 0x3f8db6cb, 0x21197a82, 0x332ae688, 0x3a539333, 0x151284c7, 0x2099}}, + {{0x27573ccc, 0x1fe32717, 0x2fcfe96e, 0x01b969cd, 0x1048dfd4, 0x2ea3972e, 0x33b1890f, 0x0f7f4aa8, 0xa5cf}}}, + /* 13*16^2*G: */ + {{{0x29078c18, 0x00bfe52b, 0x2ede9295, 0x3830f2bb, 0x1fd39b99, 0x3db9caab, 0x0ec70308, 0x1944eb30, 0x751d}}, + {{0x0ece0d67, 0x2635ba57, 0x3e05ac79, 0x02523072, 0x2a2a4ef0, 0x152ebda8, 0x24158853, 0x0fff7292, 0xba9c}}}, + /* 15*16^2*G: */ + {{{0x1e86d900, 0x0b3f3572, 0x3a3db449, 0x17b82745, 0x3a3b3640, 0x120c2280, 0x3801117b, 0x3d489711, 0x5be0}}, + {{0x358a5755, 0x13375a6f, 0x1b34f5ac, 0x085c9490, 0x35423df9, 0x1f8e939e, 0x2c422d34, 0x3679b7fc, 0x83d1}}} + }, + { + /* 1*16^3*G: */ + {{{0x2245573f, 0x01dfa36a, 0x0fd0a64f, 0x219dbcbd, 0x2d6bd250, 0x1e259cb9, 0x29e4d997, 0x2bb4b3c1, 0xe716}}, + {{0x069218d1, 0x017f09ad, 0x207c9b35, 0x0f437cbe, 0x39a851d1, 0x0ac19a1e, 0x072ab591, 0x18f9a53f, 0x3536}}}, + /* 3*16^3*G: */ + {{{0x257008ac, 0x3e61e4c1, 0x329edfb7, 0x3387b3b8, 0x1da22d19, 0x15562930, 0x07ce864e, 0x22635bd4, 0xd2bf}}, + {{0x327beb55, 0x04454d29, 0x1ff07988, 0x273842ad, 0x290c5667, 0x06576cfe, 0x377aa3f8, 0x2c72d69a, 0x69c0}}}, + /* 5*16^3*G: */ + {{{0x382f1580, 0x3435f2a5, 0x0203eb7f, 0x39377b89, 0x3064f8b0, 0x295ce47c, 0x3ce6087f, 0x0c13b960, 0x4d88}}, + {{0x1616edd7, 0x303ec5b5, 0x0eb1e110, 0x3f28ef5a, 0x3d6518aa, 0x1a002263, 0x0636ce8d, 0x139c26ac, 0x28a9}}}, + /* 7*16^3*G: */ + {{{0x20c38e11, 0x3e130f6b, 0x26e26ba5, 0x159086fa, 0x25af9e71, 0x1ce6480b, 0x00eeb326, 0x09c9f23f, 0x17c7}}, + {{0x2e90decd, 0x360d9aee, 0x20cdae3c, 0x14e65169, 0x01802e7e, 0x00bf33a4, 0x24b3c406, 0x293d3f99, 0x95c5}}}, + /* 9*16^3*G: */ + {{{0x232f36ea, 0x2557f62b, 0x13541c3d, 0x13d1a9ca, 0x0cb8b3cd, 0x0ec73f21, 0x050a8846, 0x3f6ab11d, 0x7e03}}, + {{0x0a68b8af, 0x2b308ff2, 0x05009d68, 0x27a5e693, 0x04af9941, 0x39ac5c06, 0x228da668, 0x357c4804, 0xdcf6}}}, + /* 11*16^3*G: */ + {{{0x1953baa9, 0x10f94a9b, 0x1e18de8d, 0x056ba192, 0x20b21426, 0x0deb0772, 0x3cf07616, 0x369a12c6, 0x8ce6}}, + {{0x352689e5, 0x239d70a3, 0x2a9341d7, 0x3ce61aed, 0x21b56807, 0x2cef2401, 0x3120be69, 0x13ee3ea4, 0x3d9f}}}, + /* 13*16^3*G: */ + {{{0x2f22a96a, 0x2ae3614e, 0x06ab8f94, 0x2c6ea767, 0x3ae2b008, 0x14d525d6, 0x0054a20a, 0x39cc1037, 0xb570}}, + {{0x085d1b00, 0x2ccfd987, 0x055cc9cc, 0x326ede96, 0x00cfbda7, 0x30dda6d7, 0x1e77f028, 0x2898e3dc, 0xdcd8}}}, + /* 15*16^3*G: */ + {{{0x189a7509, 0x3903ae51, 0x1fa80549, 0x09c2e590, 0x07f20de1, 0x0468f9d7, 0x3943b04a, 0x10c8f2ea, 0x44d9}}, + {{0x20437234, 0x0828ae6d, 0x14dd126e, 0x24f87f7c, 0x3b93586f, 0x08ef349d, 0x01f0a034, 0x2ce00210, 0xb2c5}}} + }, + { + /* 1*16^4*G: */ + {{{0x2eade3c4, 0x0fa11971, 0x1052a050, 0x12add272, 0x2586b471, 0x3190cd03, 0x1e90d8e5, 0x0d9bd3a4, 0xa018}}, + {{0x2b26e8d0, 0x11710809, 0x0614f37f, 0x3dca1391, 0x1d8369d5, 0x3395e0d2, 0x10b167c6, 0x3b05c504, 0xe2bb}}}, + /* 3*16^4*G: */ + {{{0x19e0af06, 0x38737ab1, 0x2ed958d6, 0x3ce62958, 0x05055c92, 0x34ed69b5, 0x1896450b, 0x07c02e23, 0x9cdf}}, + {{0x2216ade7, 0x35e8cb6d, 0x17ca5468, 0x2148b706, 0x0d94b082, 0x162ef372, 0x2ad664d9, 0x097fb4fc, 0x916d}}}, + /* 5*16^4*G: */ + {{{0x1305097e, 0x04dcae4e, 0x03ba5198, 0x3585c3a1, 0x00448338, 0x2c6cb415, 0x263edab6, 0x36757469, 0x45bf}}, + {{0x108ddc04, 0x12e8163a, 0x3d2c1595, 0x0ee74cef, 0x0ce90868, 0x220c151c, 0x2fd2bbad, 0x3704a156, 0x09d1}}}, + /* 7*16^4*G: */ + {{{0x363bd6df, 0x34c7c682, 0x166aec3c, 0x3f08f0b7, 0x095e6fd1, 0x3a7e700a, 0x2693b671, 0x2b45591d, 0xb599}}, + {{0x0efa09ac, 0x3a873a8e, 0x1134b458, 0x10313da4, 0x23c4166a, 0x1cd82e2c, 0x2b332463, 0x3477b13e, 0x6979}}}, + /* 9*16^4*G: */ + {{{0x27142d62, 0x3e184fcc, 0x03bc26da, 0x269a8d7e, 0x2854c11d, 0x18ac489f, 0x2ac0e926, 0x287c59cc, 0xf4dc}}, + {{0x3a618fc9, 0x327b3301, 0x1cd3d7fa, 0x25e6b3bf, 0x2bc659bb, 0x3ce06e46, 0x0cd46d49, 0x19f96d2d, 0x5511}}}, + /* 11*16^4*G: */ + {{{0x215fae61, 0x3b2c7fd1, 0x3395f821, 0x0571f713, 0x16bb5a7f, 0x1389039c, 0x09b66d9c, 0x1e2839b8, 0xf072}}, + {{0x096376f9, 0x1f432dd2, 0x037eabcf, 0x09c1c56e, 0x18f7d42c, 0x1e820862, 0x31ea5f7d, 0x06cac529, 0x1a68}}}, + /* 13*16^4*G: */ + {{{0x2466591f, 0x31381054, 0x3c68d6a0, 0x05cbaa3f, 0x2858ccbe, 0x0ead4cee, 0x20db0f14, 0x0915ebc2, 0x1fc5}}, + {{0x396f8cdb, 0x13bfbd5c, 0x2ec78224, 0x3e32b08c, 0x034e1629, 0x31dbf96d, 0x2bc11e9e, 0x060e0227, 0x489c}}}, + /* 15*16^4*G: */ + {{{0x322a8ebc, 0x09742e30, 0x0f967151, 0x24736dc6, 0x0a56d5a2, 0x3c2d6cc3, 0x0c5f4fd7, 0x006cc692, 0xfa25}}, + {{0x2a8a775b, 0x03649ed6, 0x0bc83318, 0x1638239b, 0x2fa8cbea, 0x14799869, 0x18962338, 0x0cac53e1, 0x71c9}}} + }, + { + /* 1*16^5*G: */ + {{{0x3d96dff1, 0x3df73b2d, 0x2d5fcfe8, 0x390c706a, 0x0d98d530, 0x1a82d5c3, 0x3e54ffef, 0x0e214507, 0x0ec7}}, + {{0x3c7b552c, 0x3b2106b1, 0x3ed78aa9, 0x149933a1, 0x0652511d, 0x3313bd60, 0x2875d91a, 0x13d3a1eb, 0xd622}}}, + /* 3*16^5*G: */ + {{{0x088d58e9, 0x070c92ac, 0x0e318385, 0x12970719, 0x02a7b6e9, 0x0a91a9f1, 0x24a86e99, 0x30ff71c1, 0x96da}}, + {{0x2ebebc5e, 0x00d24c4a, 0x087e6e38, 0x16fa26e5, 0x02c43968, 0x3312524e, 0x2c1ad856, 0x2bfceb51, 0xcb1f}}}, + /* 5*16^5*G: */ + {{{0x2db29f92, 0x254ab44c, 0x147b2c58, 0x08749c6e, 0x2b8f811d, 0x1770de2b, 0x0f312a10, 0x2c8f3ac5, 0xe297}}, + {{0x25e58ddb, 0x03ca5322, 0x1ed41416, 0x08f3aee1, 0x0d914912, 0x036eaee3, 0x370b4b48, 0x09483e32, 0xe137}}}, + /* 7*16^5*G: */ + {{{0x0ad88c33, 0x3650edee, 0x1746bcaf, 0x06b8e536, 0x24da97d9, 0x1af24834, 0x394b66b0, 0x08ce3eca, 0x1cd2}}, + {{0x248fb1b2, 0x0a3a9e10, 0x2ca1e496, 0x3f944c57, 0x36bc2713, 0x21902ac4, 0x348b096c, 0x337e0e2a, 0xfc3a}}}, + /* 9*16^5*G: */ + {{{0x3b26aa73, 0x14eb2270, 0x063a0e0f, 0x3df846c3, 0x3b1ee0cd, 0x32b4c37f, 0x1fbbfcb1, 0x35eb6e7a, 0xf462}}, + {{0x38479e73, 0x117ab05d, 0x0502cca2, 0x3a3828c0, 0x333c7a49, 0x0ee929a1, 0x053140d5, 0x03469e0d, 0x406a}}}, + /* 11*16^5*G: */ + {{{0x3cd015e3, 0x3b8780aa, 0x26502273, 0x243a565f, 0x095168af, 0x36facf2a, 0x30caf75b, 0x224974fd, 0xe0f6}}, + {{0x12157cce, 0x2a89350b, 0x22936bbd, 0x2e2d4e47, 0x34c77c55, 0x09a5b1c9, 0x03aa9536, 0x078c4392, 0x0853}}}, + /* 13*16^5*G: */ + {{{0x0bb76b12, 0x39b10c45, 0x21927691, 0x239d9dcf, 0x375a00ea, 0x20acc4ab, 0x3f57fc1d, 0x2b70554a, 0x28e4}}, + {{0x2c4747bd, 0x1f914e9f, 0x31628ff5, 0x282983c5, 0x1ea3f703, 0x12d96dae, 0x201b3f4e, 0x1313bf66, 0x14d7}}}, + /* 15*16^5*G: */ + {{{0x276ff697, 0x2fd6007f, 0x20764628, 0x26da2194, 0x2097c636, 0x07b6aece, 0x2805ed27, 0x2e89e52e, 0x85a0}}, + {{0x12142721, 0x027b5369, 0x10a58b93, 0x3a5ffe9e, 0x2daa551d, 0x1e434f73, 0x3e24a554, 0x0b987ab0, 0xadf3}}} + }, + { + /* 1*16^6*G: */ + {{{0x2392d805, 0x1c971773, 0x35405d43, 0x1ea01a61, 0x23449aa8, 0x1536abea, 0x293d7a4a, 0x3733d31a, 0xf8f5}}, + {{0x2cda02fa, 0x09986545, 0x12143ba0, 0x3cf69929, 0x21327351, 0x34f8cd91, 0x23054389, 0x1db3d9b5, 0xe581}}}, + /* 3*16^6*G: */ + {{{0x3fa046f7, 0x2752cc59, 0x207309d1, 0x0443ce40, 0x2e2d4517, 0x212b2251, 0x083a94e0, 0x2392a196, 0xe12c}}, + {{0x212646ad, 0x0e9568a2, 0x33119345, 0x03013844, 0x3126f6dd, 0x2cfb54e4, 0x1a2f3433, 0x011843f6, 0x7cec}}}, + /* 5*16^6*G: */ + {{{0x02853c43, 0x26c49fa3, 0x222e466b, 0x059b15eb, 0x11323648, 0x238bbf8f, 0x292093d0, 0x351d05e5, 0x394b}}, + {{0x2064469d, 0x05e0a332, 0x10fcf0cb, 0x0bd9c4b6, 0x160767d5, 0x38ff0bc7, 0x1c6b9207, 0x1b548547, 0x2b4d}}}, + /* 7*16^6*G: */ + {{{0x3c722e94, 0x30b75ce7, 0x1058961e, 0x36040e5b, 0x1404334e, 0x31995b16, 0x282e9445, 0x0e37ce37, 0xca85}}, + {{0x1049a527, 0x28298b7c, 0x08b26a43, 0x0254ea29, 0x3b9f12f2, 0x1cc49a87, 0x205c311e, 0x3f10bae7, 0x3b27}}}, + /* 9*16^6*G: */ + {{{0x1cad6309, 0x1c5d18a7, 0x239ff488, 0x0687f0bc, 0x267b3dd3, 0x2dd18932, 0x17b75a1b, 0x06967c8d, 0x663e}}, + {{0x09981f28, 0x0ca1ae8e, 0x2eb52bd5, 0x01f51100, 0x1cf918b9, 0x0b060f2c, 0x2a8c3c10, 0x2dcee019, 0x292f}}}, + /* 11*16^6*G: */ + {{{0x22c23d03, 0x09d6c914, 0x3c7ff249, 0x286c1363, 0x3beeab3b, 0x0db08dc1, 0x3667096c, 0x3bf9cc18, 0xa2d9}}, + {{0x3085db74, 0x00b93013, 0x039df451, 0x0269fa56, 0x101b92ea, 0x0c10db1c, 0x01b8f155, 0x148a3321, 0x1cc8}}}, + /* 13*16^6*G: */ + {{{0x07d4c6d1, 0x1d57e59c, 0x2d9fffb1, 0x18b35466, 0x3f35d0f6, 0x2442d49c, 0x1a9efe0b, 0x384ad22c, 0x5657}}, + {{0x0106bdec, 0x20c0fca6, 0x052c1418, 0x3e68d685, 0x2e6a0abf, 0x2ce43cce, 0x149f9acf, 0x2fbd2e37, 0x72b5}}}, + /* 15*16^6*G: */ + {{{0x1933564a, 0x21953755, 0x1e3af44f, 0x1a2d3ebb, 0x2d8d2b7a, 0x13b7199d, 0x2e001086, 0x18857502, 0x5b68}}, + {{0x0204ef63, 0x2d7c1162, 0x078869f3, 0x0abb88a2, 0x1d95de39, 0x0c315346, 0x2264552d, 0x3a9a73ce, 0x76b5}}} + }, + { + /* 1*16^7*G: */ + {{{0x2f922dbd, 0x21288c5d, 0x399218f9, 0x298c4587, 0x0d71b91c, 0x17aab639, 0x1af313f8, 0x2dafff53, 0x6d28}}, + {{0x20ef3cff, 0x12affc0a, 0x04da2994, 0x093a7c2e, 0x0b4a1c4c, 0x2f869873, 0x1d2fa40f, 0x36414507, 0xaf39}}}, + /* 3*16^7*G: */ + {{{0x1b168b64, 0x16437fe6, 0x186c840b, 0x14f40ab1, 0x14467ea1, 0x3c2417f0, 0x3e3ddd3d, 0x055e9fef, 0x7cd3}}, + {{0x1abbb16b, 0x15b034ad, 0x2e02e358, 0x2b1366dc, 0x1bfafb13, 0x1a39e2f3, 0x12c62205, 0x234845ca, 0x9ca0}}}, + /* 5*16^7*G: */ + {{{0x06ef29e8, 0x0ac71be8, 0x1d9aee3b, 0x371552c2, 0x05356264, 0x090c6675, 0x1f8c456b, 0x02f6d7cb, 0xed86}}, + {{0x39b90f8f, 0x00687126, 0x18daa335, 0x18c3d70b, 0x017bb1e7, 0x2fdacd01, 0x1a7fd7c6, 0x39d0dd75, 0xb837}}}, + /* 7*16^7*G: */ + {{{0x3636e617, 0x37e462cf, 0x1f1cf599, 0x37340ef0, 0x272c9d47, 0x3870b9f8, 0x21243735, 0x3323f474, 0x6868}}, + {{0x3cbb3d27, 0x323773cf, 0x0384cd71, 0x3f8c3229, 0x313f0a60, 0x1640e1e4, 0x3f9e6b3c, 0x02296e46, 0xeed0}}}, + /* 9*16^7*G: */ + {{{0x113e2a34, 0x1e768a98, 0x23a11e2c, 0x074b9973, 0x2fd31829, 0x32d27c42, 0x0fe202c5, 0x2cd83ab2, 0xec03}}, + {{0x384566d6, 0x10890fba, 0x1a136b7a, 0x2a055b99, 0x2122728a, 0x3f788404, 0x058437be, 0x03fed828, 0x8602}}}, + /* 11*16^7*G: */ + {{{0x087c1b18, 0x3ab83397, 0x04991a25, 0x078b2d52, 0x1056fa10, 0x0c0d6964, 0x0b90de6a, 0x1928e79e, 0xa794}}, + {{0x3b94809a, 0x3ad61425, 0x1562821b, 0x2637a71c, 0x1a89f60d, 0x295e1e7a, 0x058cc249, 0x3d38fdca, 0x1361}}}, + /* 13*16^7*G: */ + {{{0x1ed10d26, 0x2538a31b, 0x1e595f65, 0x26afbe0a, 0x330ccc5a, 0x247eda53, 0x3bcc790e, 0x3ca02aa3, 0x544e}}, + {{0x36dafcc2, 0x3f093dc9, 0x22c06ae2, 0x0f5be5db, 0x0d70d368, 0x2c77fa36, 0x2c2ce9d6, 0x07277116, 0x95b9}}}, + /* 15*16^7*G: */ + {{{0x37ad18e6, 0x1251e7e2, 0x13cad5e2, 0x2b4f9e63, 0x0aff9b57, 0x14f211ad, 0x0c6214de, 0x1b2217cd, 0xe2c2}}, + {{0x2554cfad, 0x36bf946a, 0x1981de4a, 0x3145729c, 0x17ba113b, 0x3899ba84, 0x0818851c, 0x06ca13d2, 0xb212}}} + }, + { + /* 1*16^8*G: */ + {{{0x185a5943, 0x296a7888, 0x065dfb63, 0x2e464d97, 0x2c71da1a, 0x15acc898, 0x2af89216, 0x1ad02bc8, 0x7fe3}}, + {{0x299ca101, 0x143454b1, 0x38af212d, 0x2cf5619e, 0x1ca6f174, 0x27d0101f, 0x236249f0, 0x3516096d, 0xe697}}}, + /* 3*16^8*G: */ + {{{0x1f0922a8, 0x1a9e0247, 0x05cf8d97, 0x243a7495, 0x2f8b808e, 0x09395808, 0x22d73809, 0x1a9016d3, 0x4b65}}, + {{0x199a80bb, 0x36b72b16, 0x1850f694, 0x1cee78ae, 0x18c4d6d4, 0x01330957, 0x3783920d, 0x28c744b9, 0xee1e}}}, + /* 5*16^8*G: */ + {{{0x29d07e9e, 0x1413e221, 0x2a60c36b, 0x279f287d, 0x3d8e5ea0, 0x2caf83ec, 0x1e13d93d, 0x255baf59, 0x9d78}}, + {{0x03d8c8ee, 0x1375856b, 0x394c7b2f, 0x1828b68e, 0x3210ce74, 0x0aa27074, 0x2a8cd654, 0x279bbd23, 0xd514}}}, + /* 7*16^8*G: */ + {{{0x3dc4950f, 0x19dd4219, 0x13942076, 0x106cab6f, 0x1b631657, 0x0da11b93, 0x13fa9572, 0x049cb84d, 0x4acb}}, + {{0x23d8b4df, 0x1b1b9111, 0x1866ac56, 0x2790a02d, 0x31e29fdf, 0x0a63db31, 0x3cdad8cf, 0x3483edd0, 0x726c}}}, + /* 9*16^8*G: */ + {{{0x2d7e8cbd, 0x1031e9ef, 0x007d816f, 0x199fe2bc, 0x01464a2a, 0x114d5432, 0x317b4234, 0x17afc69a, 0x640c}}, + {{0x3ec5a5db, 0x1b8a40f2, 0x0ff9b020, 0x01a7ec63, 0x1eab9eba, 0x271badc0, 0x0fd2f2ae, 0x223f60a7, 0xd6ae}}}, + /* 11*16^8*G: */ + {{{0x3e86bddc, 0x1c2812c1, 0x35ce3d5f, 0x349ae5e5, 0x1b6b9bf1, 0x158b2437, 0x04b32451, 0x012c6d0a, 0x8bba}}, + {{0x29e349c4, 0x088f1687, 0x0196e5f5, 0x2b3f793d, 0x19437ac6, 0x2fe4859a, 0x08ebf659, 0x26702708, 0xc340}}}, + /* 13*16^8*G: */ + {{{0x0257f582, 0x05c39e01, 0x2c3a258d, 0x26427ab7, 0x1a5fe41f, 0x1a50fdf1, 0x137e210a, 0x15d13fb3, 0x8b0a}}, + {{0x37372d4b, 0x205ffb7c, 0x31607664, 0x36d1ae9e, 0x237d4656, 0x285684df, 0x2c739662, 0x2913b035, 0x9e57}}}, + /* 15*16^8*G: */ + {{{0x185e797e, 0x3c5127e6, 0x23c31683, 0x1b8893cb, 0x1678a6f0, 0x15bd24f6, 0x078971f8, 0x3fe5f099, 0x0a13}}, + {{0x139d666f, 0x0c9eae7d, 0x180c3928, 0x1fdbc29d, 0x21dc3ff2, 0x36063a3e, 0x083d5917, 0x2592c897, 0xeb1a}}} + }, + { + /* 1*16^9*G: */ + {{{0x3dde3445, 0x2bfd3f87, 0x2aea7817, 0x2eea7768, 0x26519e76, 0x1c7f9ffc, 0x061e6853, 0x2d8e135c, 0x6965}}, + {{0x18855113, 0x3310e278, 0x25f99d97, 0x1f398146, 0x332dbef4, 0x392598e1, 0x02511325, 0x36b8e712, 0xd1bc}}}, + /* 3*16^9*G: */ + {{{0x088acfc5, 0x17903e5a, 0x2689789f, 0x3bd626cd, 0x091a71b1, 0x39f76f50, 0x1c7da027, 0x3147779d, 0xe1cb}}, + {{0x2249a225, 0x2f17fb56, 0x2bfba523, 0x34ca4afb, 0x39e23ce7, 0x09d93ff6, 0x3daedb31, 0x20e5f379, 0xec67}}}, + /* 5*16^9*G: */ + {{{0x2107ccc6, 0x163a94ff, 0x03c82287, 0x0e25f855, 0x2900481d, 0x3a74a116, 0x38aa1731, 0x099e5c44, 0x9c3f}}, + {{0x3dea9152, 0x101e5334, 0x1f9b1868, 0x2a3f53a5, 0x3e6eca51, 0x0dd7d2fc, 0x11d9c8be, 0x0306d92d, 0xdaee}}}, + /* 7*16^9*G: */ + {{{0x15a449e7, 0x0717ad0e, 0x13c2be42, 0x28a80d39, 0x00922b2f, 0x3eb05ec5, 0x32d72796, 0x3655df1a, 0x5c30}}, + {{0x2e2677d0, 0x1c3a9206, 0x3ce790e7, 0x179014f0, 0x0592d0b7, 0x2d97de67, 0x21b92164, 0x38ed6c23, 0x8025}}}, + /* 9*16^9*G: */ + {{{0x0b8ceb07, 0x2956300a, 0x3ee271cf, 0x1e494aff, 0x28d99553, 0x138ac1fa, 0x29682afe, 0x2fc8c323, 0xaa3b}}, + {{0x1fd83984, 0x26a118ba, 0x2b3f9eb9, 0x1c6caf1e, 0x1162ec3b, 0x32c3f932, 0x2c26844d, 0x032c2707, 0xe632}}}, + /* 11*16^9*G: */ + {{{0x03bfd1f1, 0x103a9556, 0x1d65732e, 0x0db70d45, 0x0001943a, 0x183f2645, 0x3418179e, 0x0c9444cc, 0xab4a}}, + {{0x08e1c233, 0x044e5843, 0x39e98cf2, 0x1f64c909, 0x2fe057a5, 0x2cef4104, 0x08668b4e, 0x192ec0db, 0xea6c}}}, + /* 13*16^9*G: */ + {{{0x0b1d6d3f, 0x2101b5e0, 0x2eebb890, 0x0dd9a293, 0x25a8105f, 0x0dfd7362, 0x15d77f73, 0x2c96777b, 0xdba9}}, + {{0x09cd8133, 0x10ba4a0a, 0x12bd93cc, 0x2f66f114, 0x2b871448, 0x2a653d3f, 0x35b7b5ac, 0x0b4fd5d4, 0xb386}}}, + /* 15*16^9*G: */ + {{{0x31fa2a6a, 0x1e680e00, 0x30e4b256, 0x3f075616, 0x23cdfe34, 0x375d0ac6, 0x0274507a, 0x3d310ba6, 0x1998}}, + {{0x06415142, 0x01fb6d2f, 0x37258b56, 0x1b008e1e, 0x38a1e94c, 0x03e0022d, 0x2fa10970, 0x105b4642, 0x2ebb}}} + }, + { + /* 1*16^10*G: */ + {{{0x0d9aefbd, 0x163f29b1, 0x3b957752, 0x3f91ec9c, 0x3c43dc1e, 0x2a7c3506, 0x29d7632c, 0x0d072319, 0x0fbc}}, + {{0x13e71ca0, 0x34edbaa7, 0x00a9ff1e, 0x02c1a788, 0x17d3d395, 0x052c7525, 0x20e3fe40, 0x0898cbcd, 0xbd80}}}, + /* 3*16^10*G: */ + {{{0x29434837, 0x1e5b7ffb, 0x220c1bb8, 0x2cc502e1, 0x0fb06dad, 0x1071bfed, 0x07aedb13, 0x062af12a, 0xd76d}}, + {{0x3b215b4c, 0x3ea813e6, 0x1b7ccc24, 0x291639dd, 0x2b933290, 0x390853de, 0x16644de0, 0x1368cbb6, 0xf6bc}}}, + /* 5*16^10*G: */ + {{{0x1c07f222, 0x0ba27c86, 0x060fe7d0, 0x388718eb, 0x1753d1c5, 0x2074687c, 0x3ff604f4, 0x31941859, 0xd5c0}}, + {{0x0c6ffd57, 0x0bbda478, 0x0813a86e, 0x3cfd469e, 0x1f75b9ba, 0x3831dfd2, 0x3b8850cd, 0x02e18205, 0x15a3}}}, + /* 7*16^10*G: */ + {{{0x0e93bfa6, 0x291c5a89, 0x1a1362a4, 0x274a5682, 0x0c9fe0d3, 0x272e99ad, 0x2f62ce54, 0x0d939291, 0x734c}}, + {{0x18d10774, 0x31be9e66, 0x10297c4f, 0x284d8822, 0x0c5f48ec, 0x26078d48, 0x39d049de, 0x0540eaa9, 0x0995}}}, + /* 9*16^10*G: */ + {{{0x1fa194ae, 0x03ad45fd, 0x2054aecf, 0x100a4766, 0x1eb14906, 0x1d7674aa, 0x26a89011, 0x367681ed, 0x79a3}}, + {{0x1fcf634b, 0x3f197a72, 0x379bc4d4, 0x35097ccb, 0x2f03d86b, 0x19c6e162, 0x0b1b34b3, 0x36f29c95, 0x84e1}}}, + /* 11*16^10*G: */ + {{{0x21e8b7fe, 0x2b241800, 0x385b26a6, 0x3438b85d, 0x3c98e05d, 0x3932ab73, 0x305828a3, 0x3f425356, 0x3393}}, + {{0x023c6821, 0x30509108, 0x29b94b70, 0x15acc2a2, 0x1a668d8e, 0x3fabb671, 0x3beb82ea, 0x0defb219, 0x1304}}}, + /* 13*16^10*G: */ + {{{0x21528cf6, 0x0255e755, 0x250694ea, 0x280942bd, 0x1b0a52e6, 0x2d161bb9, 0x227e15e1, 0x0a2184d1, 0xa16b}}, + {{0x3ce93f3b, 0x02e483e7, 0x3cc80138, 0x24fef204, 0x1150f434, 0x33b5e760, 0x3ad99913, 0x262ba14d, 0xf405}}}, + /* 15*16^10*G: */ + {{{0x0c8db2e0, 0x144299ae, 0x30d73583, 0x0f2f7057, 0x1a74f647, 0x3226aea5, 0x3474cbf6, 0x33880638, 0xd317}}, + {{0x274bc9a9, 0x16cd28ac, 0x2b860f3a, 0x289d3408, 0x179136ca, 0x0b0fa38e, 0x3844b99c, 0x0842a424, 0xd61a}}} + }, + { + /* 1*16^11*G: */ + {{{0x23fe67b2, 0x1b8c65ea, 0x22e3338c, 0x2a2ff9c2, 0x3323b234, 0x19ae6ea5, 0x085dcbc6, 0x3090ddcf, 0x6608}}, + {{0x25b47a28, 0x248ff973, 0x0c543081, 0x0ac567d0, 0x06e03fc2, 0x3d90369d, 0x1c168846, 0x05afb148, 0xa1a9}}}, + /* 3*16^11*G: */ + {{{0x2bc73e02, 0x0f9baab4, 0x365312c1, 0x259853ba, 0x17863184, 0x2a6045f5, 0x1dc23206, 0x1ab8a9b1, 0xf095}}, + {{0x0611219d, 0x34b3da66, 0x3ae94572, 0x0b41236e, 0x03935667, 0x08162bca, 0x0e03c76e, 0x39980451, 0x433f}}}, + /* 5*16^11*G: */ + {{{0x1c5fe45c, 0x3788b794, 0x07c0f597, 0x2ca06a0e, 0x37283488, 0x3c9275f3, 0x2a60ca52, 0x3afa8f28, 0xdb98}}, + {{0x3ef45a22, 0x129c0710, 0x2480e1c4, 0x20c813ea, 0x112c8ce9, 0x144a7762, 0x185a2de1, 0x3cc2dd6f, 0xe0c0}}}, + /* 7*16^11*G: */ + {{{0x22128eac, 0x3d679837, 0x0af1ccba, 0x11d63573, 0x2a51690c, 0x29acedf5, 0x1a5f421b, 0x300582b7, 0x0a73}}, + {{0x24f1180d, 0x2164a475, 0x355d9ca3, 0x0dd67c5d, 0x350a7c79, 0x32db7653, 0x2838ca55, 0x36958113, 0x443f}}}, + /* 9*16^11*G: */ + {{{0x23ccbc30, 0x196a4cc5, 0x1349618c, 0x37f97487, 0x0997249e, 0x34dd99e8, 0x34f2370e, 0x0830d1f2, 0x3787}}, + {{0x1315729e, 0x2880c9fc, 0x1348f846, 0x2f3e5574, 0x279b6d16, 0x062b02aa, 0x2538c931, 0x376e73dc, 0x8f1b}}}, + /* 11*16^11*G: */ + {{{0x03bb1b6b, 0x192a3795, 0x07c2bfaa, 0x17fbccbd, 0x15a62157, 0x20463041, 0x31a619d9, 0x34876de2, 0xfe8f}}, + {{0x30eaaf93, 0x1ed766e8, 0x0abf8899, 0x053773fc, 0x2d13c00f, 0x0a3a57d6, 0x16e3769e, 0x08abb0c9, 0x791e}}}, + /* 13*16^11*G: */ + {{{0x344b7cea, 0x20156672, 0x16cf87de, 0x111a5024, 0x33dcca47, 0x010089e2, 0x37e2ee82, 0x07f55e7e, 0x2c33}}, + {{0x15d1c9c2, 0x3f0ad1ab, 0x13094077, 0x249447fc, 0x3dd65061, 0x0fcf630e, 0x21e76fcf, 0x1ec73381, 0x2056}}}, + /* 15*16^11*G: */ + {{{0x0112278c, 0x3e4a6cde, 0x28d9a158, 0x00592742, 0x044b66dd, 0x22d321fe, 0x1a320a34, 0x301b1194, 0x509b}}, + {{0x0e178f66, 0x321d7262, 0x335f945e, 0x197fa1b9, 0x0f64570f, 0x03d3c5ee, 0x246ec176, 0x1a30adc8, 0xb4b1}}} + }, + { + /* 1*16^12*G: */ + {{{0x17e55104, 0x0baebe00, 0x38e9c71c, 0x0ea0d7ee, 0x0b561cf7, 0x3a4f0d36, 0x3873763d, 0x1d9489ed, 0xd8de}}, + {{0x252e08cd, 0x280bbe03, 0x140db1b2, 0x3dcff386, 0x1cf924c2, 0x318a2b47, 0x3f2d15c4, 0x25196f84, 0x2fd2}}}, + /* 3*16^12*G: */ + {{{0x2987bfd3, 0x24e70b1f, 0x0c4284c6, 0x3151cbfd, 0x1dd19187, 0x37efabeb, 0x18e33551, 0x1e1bef54, 0xe3a5}}, + {{0x0cc23e7d, 0x3b4c6db2, 0x128e0817, 0x373cbb36, 0x18210ca3, 0x1ee7fd2b, 0x040e6847, 0x2b4254d6, 0xf74b}}}, + /* 5*16^12*G: */ + {{{0x22d5056e, 0x19e54748, 0x247a07cb, 0x372d69f8, 0x2e5e480e, 0x097ff3a5, 0x120d4115, 0x1c107b29, 0x42a9}}, + {{0x30f7db11, 0x21053722, 0x29fd1fd4, 0x13920f5b, 0x163b26b6, 0x0db749ad, 0x087066ec, 0x1fd9b3c0, 0xf2fc}}}, + /* 7*16^12*G: */ + {{{0x13dafd3b, 0x19d17e47, 0x1cb3956c, 0x2e267c0b, 0x1379d66f, 0x0cb0bb59, 0x3964cfe2, 0x29c6c709, 0x0d6c}}, + {{0x1a6fe6e8, 0x1ab7c508, 0x288771ad, 0x08922afb, 0x07de58a0, 0x1252809c, 0x2293d9fe, 0x0c2ce3f7, 0xa851}}}, + /* 9*16^12*G: */ + {{{0x31131f8b, 0x1afe71ff, 0x3a20d4df, 0x191a5833, 0x031fb469, 0x308b7e71, 0x1a3d97d4, 0x329eb619, 0x05ed}}, + {{0x3a6f779f, 0x3b3c2c66, 0x0e89d490, 0x1494017c, 0x0271be33, 0x275c6d7c, 0x086bc01c, 0x2207923a, 0x9e58}}}, + /* 11*16^12*G: */ + {{{0x2b597e4d, 0x323e7d07, 0x37d1a319, 0x1d3cc979, 0x371c1149, 0x2d168ced, 0x3a0a4121, 0x301582f1, 0x5a13}}, + {{0x241856e0, 0x3df921a7, 0x1136664a, 0x37a1ead6, 0x2d73ce7b, 0x346283c8, 0x397ff51f, 0x0f04e243, 0xc9e7}}}, + /* 13*16^12*G: */ + {{{0x0260faf0, 0x2a9e2585, 0x3e95935d, 0x2ef4d165, 0x0f272ea2, 0x113869a0, 0x36e75431, 0x1595805e, 0x96b2}}, + {{0x2366d412, 0x03909483, 0x07d4f5ac, 0x02efe61c, 0x3f99e189, 0x36395cce, 0x37cac00a, 0x29a8006c, 0xdcf8}}}, + /* 15*16^12*G: */ + {{{0x2ad13276, 0x12686f92, 0x1c043c7a, 0x18d43aba, 0x3771a3ca, 0x04acace1, 0x0de2426f, 0x06443107, 0x0b97}}, + {{0x0a84dadb, 0x0ce3cd08, 0x270fae3b, 0x0f5e4a60, 0x36811f59, 0x0b916cef, 0x2eefbd4e, 0x121bbc01, 0xac28}}} + }, + { + /* 1*16^13*G: */ + {{{0x071e5c83, 0x3a9af248, 0x142a0bee, 0x349fc661, 0x18e5b18b, 0x2116dca9, 0x2d73f20a, 0x32505409, 0x54cc}}, + {{0x140916a1, 0x3f423bdc, 0x18ee496c, 0x2782f317, 0x12bf2292, 0x3e1c576b, 0x145323a8, 0x0fd16d14, 0x1c43}}}, + /* 3*16^13*G: */ + {{{0x2f76167c, 0x3178d88a, 0x07467394, 0x0bd08b31, 0x0cd9f22f, 0x08b1a4b7, 0x2ff9539c, 0x0bb72dcf, 0x8758}}, + {{0x2f4d7ff6, 0x31beed85, 0x3197be86, 0x00a3c19d, 0x3236a888, 0x040b0f0d, 0x24a7bfde, 0x250d42b5, 0x075b}}}, + /* 5*16^13*G: */ + {{{0x34de6611, 0x19c8fba1, 0x3821fb04, 0x3d95ce52, 0x26f11e33, 0x16dcd8d5, 0x336db1c2, 0x1eb287c9, 0x4a10}}, + {{0x18a805fe, 0x0d63afb9, 0x02132ac0, 0x17551e97, 0x00052e07, 0x3993a3dc, 0x3ef3934c, 0x09944018, 0x809b}}}, + /* 7*16^13*G: */ + {{{0x2dcfecb0, 0x32e93b41, 0x0a8d846f, 0x20ff474c, 0x3f49f6e9, 0x28383526, 0x2dfc9654, 0x0bacdcaa, 0xfd40}}, + {{0x2da08de8, 0x0164fcf7, 0x1e65e791, 0x12d3092f, 0x2ba86b1a, 0x1898e26e, 0x23a22e9a, 0x100c3769, 0xd6b3}}}, + /* 9*16^13*G: */ + {{{0x154659ed, 0x2d37583d, 0x15d966e5, 0x2b8f4886, 0x09d0a07f, 0x2e381ffb, 0x075155df, 0x2cd19186, 0x467b}}, + {{0x2800cf83, 0x2c81f42c, 0x1013e009, 0x06f04373, 0x382cd370, 0x0b3561b6, 0x178e8a1f, 0x3ff416aa, 0xd01e}}}, + /* 11*16^13*G: */ + {{{0x1c97e515, 0x3992612b, 0x1885a5fe, 0x0535b0ce, 0x1ec7e569, 0x1e6d8c3a, 0x1c0e46c8, 0x2e63e337, 0xcf66}}, + {{0x006c8a51, 0x160853aa, 0x190033a9, 0x3c1d1636, 0x2c6a7b33, 0x16d040d3, 0x061211c2, 0x1c5ee411, 0x0a70}}}, + /* 13*16^13*G: */ + {{{0x186154e5, 0x2e94a840, 0x2afa0dd3, 0x100a99a6, 0x08677086, 0x32254eb5, 0x3aa34751, 0x14b183ef, 0x3d92}}, + {{0x1603a8a2, 0x1ff24fda, 0x07dd7077, 0x287edf5f, 0x2b4cf3ae, 0x24cd0a25, 0x29d7fc44, 0x007734be, 0x3d0d}}}, + /* 15*16^13*G: */ + {{{0x2a4a8daa, 0x0ed8ed8a, 0x28a5ca3d, 0x041803bc, 0x0a968ce5, 0x3ad6d23d, 0x1769c760, 0x0e2c9a22, 0x2bbe}}, + {{0x1236e49b, 0x3821dd3a, 0x3eb6e7d7, 0x00ace938, 0x16085099, 0x33fbe47e, 0x3b36f5e2, 0x01fd8034, 0xf857}}} + }, + { + /* 1*16^14*G: */ + {{{0x22d32936, 0x0c3eddc4, 0x2847f01c, 0x03340b8c, 0x3d7f38e4, 0x331f4544, 0x0a47d9f6, 0x03165e05, 0xc544}}, + {{0x07cabfd4, 0x290be8dd, 0x1e41e5d9, 0x29b4a18c, 0x2cf4acd8, 0x3078748f, 0x21fa72ed, 0x3a6e8e0f, 0xd27e}}}, + /* 3*16^14*G: */ + {{{0x3989a8e1, 0x361407b1, 0x0ee4bdd7, 0x0765bcdd, 0x1cfe0a7c, 0x03811e6e, 0x3a79b750, 0x00f11737, 0x3e4d}}, + {{0x041c240a, 0x21e44e21, 0x3bd67409, 0x2bc6357c, 0x0aa719ff, 0x045f2b5f, 0x26475aac, 0x11342056, 0x12f7}}}, + /* 5*16^14*G: */ + {{{0x19bb7902, 0x24e6a343, 0x2b7c73f6, 0x309b1ca1, 0x085e9fd8, 0x28927a51, 0x210359a9, 0x21126cf5, 0x01b6}}, + {{0x203ee653, 0x35fd12c7, 0x1836682c, 0x3ac9811c, 0x2d1581fc, 0x0663970d, 0x39c3e0bf, 0x18e87a4d, 0xe590}}}, + /* 7*16^14*G: */ + {{{0x0371d9fe, 0x0a6d5b53, 0x199d6bbc, 0x12cd5b06, 0x2b3a4cf0, 0x25569f0e, 0x09ca2335, 0x0f2c6b33, 0x952c}}, + {{0x0189a13f, 0x1db39b49, 0x008c75ed, 0x11193c46, 0x2ce5d066, 0x3e44dbdb, 0x22f06a7d, 0x2151bdf5, 0x59b9}}}, + /* 9*16^14*G: */ + {{{0x0bc2c885, 0x11fff1da, 0x264e57c8, 0x147b9dd4, 0x17cde515, 0x2601142e, 0x26eac858, 0x13b856c5, 0xdfcb}}, + {{0x1345d92e, 0x1752990c, 0x3abe9757, 0x1dce251e, 0x2c0f411c, 0x13f09b20, 0x213a153c, 0x08e55541, 0x536a}}}, + /* 11*16^14*G: */ + {{{0x3510208e, 0x0e2e14af, 0x0d794387, 0x23338b61, 0x3c97bbdb, 0x1ebce811, 0x2500c8a8, 0x19b026f9, 0x1579}}, + {{0x0d207357, 0x183bb894, 0x2da43dfd, 0x23f1910c, 0x0cbe0700, 0x3fdedeee, 0x2264eabd, 0x1b56adc4, 0x4044}}}, + /* 13*16^14*G: */ + {{{0x0b96fe13, 0x327f32fa, 0x0852ea81, 0x2492b4ed, 0x3f6e23e4, 0x06a3fe04, 0x2990ad6e, 0x078f12c7, 0xc6b2}}, + {{0x37bb1417, 0x001ae5ab, 0x1e6d2d6a, 0x1954245e, 0x2b28a2ff, 0x2de078d3, 0x34d48e54, 0x337630cc, 0x335b}}}, + /* 15*16^14*G: */ + {{{0x03936565, 0x0d96066b, 0x37fa4c7c, 0x29ecdb65, 0x1522d997, 0x2f2a754e, 0x3296f0b4, 0x39311e31, 0xa231}}, + {{0x35ec5f19, 0x2b95a818, 0x2f154268, 0x295b8025, 0x03cf942b, 0x253b1a20, 0x3be91c0d, 0x3262fb1f, 0x80e0}}} + }, + { + /* 1*16^15*G: */ + {{{0x3066fd48, 0x3e7d05ca, 0x0971583b, 0x0dc4072e, 0x3adca61c, 0x1e6e5e9a, 0x3f1c506c, 0x159e9089, 0x241c}}, + {{0x12857b08, 0x3df4b19e, 0x2a366057, 0x2a1c4e2b, 0x3203a48e, 0x0e05f010, 0x02d4b936, 0x0b64f50c, 0x40a6}}}, + /* 3*16^15*G: */ + {{{0x0df9591d, 0x187df6e4, 0x2b4c82a8, 0x3b0eb090, 0x327218dc, 0x034f12ac, 0x178e9cba, 0x348ee09a, 0xde2f}}, + {{0x0457ad84, 0x13865cf4, 0x0c036a4b, 0x26a287e2, 0x392ebbda, 0x32dfb212, 0x243f305e, 0x1c44ced8, 0x400d}}}, + /* 5*16^15*G: */ + {{{0x3562282c, 0x3aa0952b, 0x0fbc3772, 0x0bcebe4e, 0x211340f0, 0x2522c093, 0x0cbdd993, 0x226c0c13, 0x8df8}}, + {{0x21d195cd, 0x095aaf65, 0x2f9bb157, 0x1fdc1133, 0x0af35e24, 0x10798c62, 0x1ceed6c7, 0x16d9cc81, 0x7452}}}, + /* 7*16^15*G: */ + {{{0x0dddb2dd, 0x2754a254, 0x02c0da6f, 0x22193373, 0x12f24507, 0x3ee033c5, 0x380f8001, 0x1d633662, 0xa0fd}}, + {{0x33ede6b2, 0x3f653fe1, 0x1409a7c7, 0x233a5be2, 0x308f311c, 0x247f4c4e, 0x368d5f86, 0x360d704c, 0x53e5}}}, + /* 9*16^15*G: */ + {{{0x0f542e36, 0x0232ea81, 0x13415c2e, 0x08bfebe8, 0x2335d84e, 0x16499e51, 0x1a0f67de, 0x31611cb4, 0x3170}}, + {{0x363288b5, 0x1b11d6bb, 0x199be1bc, 0x1bdd5a56, 0x39773d00, 0x05424ffa, 0x27fe2375, 0x0d84bf0e, 0xb208}}}, + /* 11*16^15*G: */ + {{{0x1c7548e9, 0x266c8e97, 0x092d54c7, 0x376a01c2, 0x063fe5d8, 0x1205a53c, 0x13e029db, 0x2c2a428b, 0x92fa}}, + {{0x0917758f, 0x31c4b341, 0x32d08488, 0x28371a3b, 0x2679ffc8, 0x05c53830, 0x246bcf43, 0x2d1a032c, 0x55e7}}}, + /* 13*16^15*G: */ + {{{0x1498f7f8, 0x0360142e, 0x2411622e, 0x37d9f4c9, 0x2c8712c4, 0x2f846c64, 0x355179d0, 0x196f8600, 0x91b0}}, + {{0x3f23195b, 0x31d03678, 0x389639e3, 0x0b1ed095, 0x17e264df, 0x3fcd2400, 0x31620ff9, 0x1bddfed9, 0x035b}}}, + /* 15*16^15*G: */ + {{{0x0060e322, 0x0772fb89, 0x1c4d14b5, 0x3371cdea, 0x1ab9923e, 0x241a5d22, 0x1cb3a9c3, 0x07d332b2, 0x8e4a}}, + {{0x104619d7, 0x38860f36, 0x14fbfe04, 0x002a6365, 0x2e7bc4fb, 0x017b4901, 0x0d7752fb, 0x2dd7acca, 0x4936}}} + }, + { + /* 1*16^16*G: */ + {{{0x0e14db63, 0x039d72d2, 0x1651f7e9, 0x124eeaab, 0x2e25de29, 0x0964b8c9, 0x1aaa5849, 0x08af0a04, 0x0fa8}}, + {{0x1f462ee7, 0x10449151, 0x0fe82f5e, 0x2c699414, 0x1f188b34, 0x2b52f2cf, 0x3a80d6f4, 0x12ba3d76, 0xbff4}}}, + /* 3*16^16*G: */ + {{{0x3db3cdec, 0x14b114fd, 0x228ebf57, 0x3bce84ac, 0x2a4bc8db, 0x199179ef, 0x12f5ce59, 0x30193fe4, 0x85b2}}, + {{0x0a03f81f, 0x3d342081, 0x24cf8e08, 0x2602cd39, 0x0c6d00dc, 0x1fe8b4bf, 0x1153663c, 0x09e3ce74, 0xf64b}}}, + /* 5*16^16*G: */ + {{{0x0607b030, 0x22296b92, 0x184d6732, 0x36bfd8f9, 0x16f29c24, 0x07eeb3b0, 0x21467785, 0x00ddb100, 0x110b}}, + {{0x33617c3a, 0x10ea844a, 0x3298749f, 0x2f8555be, 0x21c70c87, 0x3ae27e11, 0x2e6734c6, 0x0ae14c63, 0x8443}}}, + /* 7*16^16*G: */ + {{{0x35a76f08, 0x13b76071, 0x3bbed4e5, 0x257c94e2, 0x1caaf832, 0x1b8490ac, 0x071d714f, 0x139127d9, 0x1878}}, + {{0x2b824993, 0x2ce58175, 0x20a25320, 0x275d29e9, 0x31e671fc, 0x1ea3f6b1, 0x21ae7177, 0x3b5fd287, 0x8d76}}}, + /* 9*16^16*G: */ + {{{0x3a6fad81, 0x3a38cf27, 0x00cb03ec, 0x0cd95d23, 0x3a037d9c, 0x15b75dc0, 0x1e6b9aef, 0x3e781f41, 0x58a2}}, + {{0x3b109594, 0x10018578, 0x1300b825, 0x22ecb4cb, 0x3fa6bd79, 0x1a0be1c5, 0x160e0c1b, 0x19316b15, 0x06ab}}}, + /* 11*16^16*G: */ + {{{0x1eb52583, 0x2c8bc47e, 0x10cc13af, 0x22a673b0, 0x0f676fea, 0x39b6ec9e, 0x2bba240e, 0x0837339f, 0x1ef0}}, + {{0x3a3f17ae, 0x16c9e065, 0x012d4cb5, 0x30c03e5c, 0x1695306a, 0x3db03d2e, 0x214b0097, 0x1dac969e, 0x5944}}}, + /* 13*16^16*G: */ + {{{0x30a1958f, 0x1708fb07, 0x3b56643b, 0x0e6d491b, 0x3fa32c4f, 0x345133ea, 0x2a21395d, 0x2058f075, 0x4e4a}}, + {{0x08636f8a, 0x10ecfd45, 0x2c43d66a, 0x010217ec, 0x1c6fa840, 0x3d28fb8a, 0x0c8d1033, 0x2916de7a, 0x2574}}}, + /* 15*16^16*G: */ + {{{0x24935db5, 0x209d6a11, 0x06bdb0ee, 0x05e60987, 0x14519e28, 0x09f83b56, 0x21104e33, 0x1a85ab75, 0xf696}}, + {{0x1d166838, 0x28d20db0, 0x001bf013, 0x1d14e8d1, 0x3c755e2d, 0x17b95cb0, 0x31db2c1a, 0x38c1ea40, 0xba0d}}} + }, + { + /* 1*16^17*G: */ + {{{0x376a6987, 0x23d04c16, 0x3da43ff6, 0x1206ad10, 0x2e1b3f2b, 0x31a6235f, 0x099547dd, 0x0635ea66, 0x54bc}}, + {{0x1b9aae49, 0x3915f341, 0x373b119f, 0x3ae3b52e, 0x33e2fd52, 0x06e146e9, 0x2eaf3739, 0x23048479, 0x4b2c}}}, + /* 3*16^17*G: */ + {{{0x3d1fd820, 0x22fd1fd7, 0x07675003, 0x21e15192, 0x31271b78, 0x0d40898a, 0x1c52aa86, 0x2f3da030, 0xbafb}}, + {{0x1bf074f0, 0x2bb6b548, 0x31fcad6e, 0x070d2848, 0x1bc0fde8, 0x1efd6b22, 0x0dd812ce, 0x265f276d, 0x1487}}}, + /* 5*16^17*G: */ + {{{0x14299b7e, 0x245c204a, 0x186e0d0e, 0x39e7cb42, 0x0220ec24, 0x30eff1d7, 0x389fe2a3, 0x0e3dc40c, 0x9b19}}, + {{0x047b84de, 0x15eca15d, 0x06b8232c, 0x337a147e, 0x2a3ec90a, 0x03a63872, 0x10283314, 0x2a9bbc5c, 0xfb12}}}, + /* 7*16^17*G: */ + {{{0x110cc4c4, 0x35041d03, 0x0a53da0f, 0x074d68b1, 0x361b2cb7, 0x207f7019, 0x175907c3, 0x06617300, 0xa677}}, + {{0x3c976570, 0x083cec8d, 0x2ff3094c, 0x1d15dce9, 0x1d9c3dbc, 0x2f598079, 0x0dd98f29, 0x18617dd4, 0x8550}}}, + /* 9*16^17*G: */ + {{{0x14242a28, 0x104200b5, 0x13ca7715, 0x16f2c849, 0x374eca45, 0x22bde12d, 0x2afc109e, 0x3b54dac3, 0x88b7}}, + {{0x394ed8ce, 0x2e5a07b1, 0x383e347f, 0x0d9a8723, 0x07bd934e, 0x2fe774d6, 0x1345e47f, 0x14c81891, 0x22b0}}}, + /* 11*16^17*G: */ + {{{0x1bc1a94c, 0x058513b2, 0x271daf80, 0x19c74acf, 0x1e875751, 0x35cac089, 0x2b3d2052, 0x05004aa1, 0x0371}}, + {{0x2fc2073c, 0x30302db3, 0x2c424838, 0x14630d8a, 0x105335c8, 0x3086952b, 0x17390ef8, 0x1a4f5477, 0x4d1d}}}, + /* 13*16^17*G: */ + {{{0x077f88ba, 0x3ef47826, 0x29bed36e, 0x2601de7b, 0x2a2cc350, 0x168cba13, 0x0293e34b, 0x08532261, 0xcc98}}, + {{0x07885278, 0x2918bbf2, 0x3354c4e0, 0x3d839fbb, 0x3d63abef, 0x3129919d, 0x1afa9114, 0x2d3a3949, 0x04eb}}}, + /* 15*16^17*G: */ + {{{0x3d70187c, 0x15cc6537, 0x3640c7f1, 0x06b218a6, 0x0f5bf875, 0x139780a4, 0x2a10f981, 0x2b80a690, 0x0ad3}}, + {{0x3fc775a7, 0x37ff3d2c, 0x262a0f67, 0x0d3ec205, 0x2bb33dd0, 0x3157c17e, 0x046e3785, 0x10351d62, 0x2af0}}} + }, + { + /* 1*16^18*G: */ + {{{0x30aae231, 0x02abeb45, 0x1f96b7c6, 0x252e149e, 0x27756f51, 0x09208e49, 0x1e3f285f, 0x325a65d8, 0x1d35}}, + {{0x0cd6ac71, 0x219c18eb, 0x29a66f15, 0x3d62a91c, 0x2bf810ed, 0x182ad88b, 0x208231d6, 0x1b2d8b7d, 0xc722}}}, + /* 3*16^18*G: */ + {{{0x0cfa3fac, 0x3834ff86, 0x32b8193c, 0x2b61a7f0, 0x0d803023, 0x3aed1758, 0x2234ce2c, 0x1011e9b4, 0xdf3d}}, + {{0x0fc7d419, 0x1189b64e, 0x2882975f, 0x358f3925, 0x0f9dbfaf, 0x2887ca70, 0x140db24a, 0x1bd48a7f, 0x48fa}}}, + /* 5*16^18*G: */ + {{{0x1f1322d4, 0x3b6496b8, 0x2ccdcbba, 0x029a5012, 0x11f822cb, 0x39b1328c, 0x16144ea1, 0x2bdaac7e, 0xdbb2}}, + {{0x0a8c5311, 0x2924ad3d, 0x37e3a5fa, 0x27f25e1e, 0x033f9d9a, 0x18347b59, 0x3561aa1b, 0x1d6e4bc4, 0xebae}}}, + /* 7*16^18*G: */ + {{{0x21138f7b, 0x01a68cf2, 0x1f2e8f2f, 0x30724f8b, 0x1b5f0bc4, 0x2a2899fe, 0x21fd4caf, 0x1ed65fc9, 0x1dba}}, + {{0x239bf268, 0x320b631e, 0x18232c0d, 0x0db9ade6, 0x0007f581, 0x06401aee, 0x3efc63ae, 0x1f4f9779, 0x6aaf}}}, + /* 9*16^18*G: */ + {{{0x179a70af, 0x36a1ddc0, 0x364df288, 0x2750a6a6, 0x1305c6ec, 0x2fa0b57d, 0x2919d31b, 0x0b910989, 0x348a}}, + {{0x07b66e82, 0x2a121852, 0x3e13e5ac, 0x29f0b16d, 0x230105b2, 0x11ef3800, 0x23e808c7, 0x3e9e7d56, 0xa1b9}}}, + /* 11*16^18*G: */ + {{{0x04d3a201, 0x1d1db5db, 0x19b9eefc, 0x3a49a93f, 0x1adf5f36, 0x293efe4c, 0x09e1ca86, 0x32146667, 0x3a4e}}, + {{0x28635f89, 0x36165bdd, 0x33cd55bd, 0x34c796bd, 0x374a8b27, 0x00f04691, 0x262de69e, 0x0bbe0bd8, 0xc99a}}}, + /* 13*16^18*G: */ + {{{0x1c978567, 0x3beb9cbf, 0x0dc1f981, 0x1769a210, 0x31f60be1, 0x24d758bf, 0x0d45784e, 0x14b620cd, 0xb1ba}}, + {{0x362dc291, 0x1fe920a8, 0x2fcd40a7, 0x291b2c2e, 0x1bb78fd9, 0x3df3dc4f, 0x143a77c5, 0x2bb1ea1a, 0xa46b}}}, + /* 15*16^18*G: */ + {{{0x12350da1, 0x08a3ba94, 0x175f043d, 0x10531df0, 0x212c2f19, 0x22dee5a5, 0x2aafd271, 0x3acf63bc, 0x0ae6}}, + {{0x30a14bc3, 0x1cf827cd, 0x143da4bc, 0x351a3c3b, 0x0189b566, 0x00d3dff1, 0x06cae2dd, 0x3ba7ed80, 0x99cd}}} + }, + { + /* 1*16^19*G: */ + {{{0x350e4f5f, 0x15cabaa1, 0x167e0e65, 0x3d72a6a9, 0x02f29acb, 0x3fc3dea8, 0x35aef388, 0x2a566112, 0x55d9}}, + {{0x3ca97db0, 0x2163adda, 0x3ad1b15c, 0x2604318c, 0x08ec524c, 0x355d3ef3, 0x2d203766, 0x1fe6a976, 0x69cb}}}, + /* 3*16^19*G: */ + {{{0x3eb142e9, 0x01aa621f, 0x207fcfbc, 0x1dbac191, 0x2ed480c1, 0x361a0e3e, 0x33e11794, 0x10faf91b, 0x4b00}}, + {{0x22c68552, 0x12cb14b5, 0x21258880, 0x08ca43ce, 0x222d870f, 0x1e2118d8, 0x1ac1adb1, 0x33c8e8c3, 0x173c}}}, + /* 5*16^19*G: */ + {{{0x17f1aa96, 0x1b752b9c, 0x0ff6481f, 0x35e97dcd, 0x3463c513, 0x0a372edc, 0x16fc2327, 0x349e64ab, 0x79ea}}, + {{0x0b0a3fb7, 0x02e9c739, 0x1b3955a8, 0x2135c444, 0x256542de, 0x390e4d58, 0x2dabf1a6, 0x3a73feea, 0xa95d}}}, + /* 7*16^19*G: */ + {{{0x393a9ae6, 0x201729cb, 0x077f8adc, 0x382a8167, 0x2d743f8e, 0x1e78d8c6, 0x1a1ceb52, 0x00143c93, 0x318e}}, + {{0x1c447d79, 0x212d5a53, 0x2d3a8ee1, 0x14dbf6eb, 0x104bd094, 0x05f29479, 0x29299f4d, 0x3b844673, 0x2792}}}, + /* 9*16^19*G: */ + {{{0x1d30585a, 0x0de516d3, 0x35014951, 0x3fe286a8, 0x00a4b495, 0x00cbd243, 0x1e43bb88, 0x151c74bc, 0x6bbc}}, + {{0x348b05f3, 0x2be5fbbc, 0x2f9ead96, 0x3c10a040, 0x2226be09, 0x3b8ac57c, 0x129f04a9, 0x0626c305, 0x467b}}}, + /* 11*16^19*G: */ + {{{0x00136275, 0x1893e023, 0x38775352, 0x11f0005c, 0x360d78a6, 0x146a43dd, 0x1fd1189b, 0x12318430, 0x9401}}, + {{0x1997aa47, 0x358e8445, 0x04e1a425, 0x12ceb958, 0x05d6695d, 0x09312ad4, 0x3a4f77aa, 0x3e57c4d9, 0x6967}}}, + /* 13*16^19*G: */ + {{{0x1f0fe850, 0x0e84f74e, 0x111a7bdc, 0x1348c2f9, 0x25f98e86, 0x15b24a36, 0x1b49c91b, 0x0ce4980e, 0xc418}}, + {{0x3d38666d, 0x0d63d11a, 0x01a0af01, 0x169fb278, 0x2fd55806, 0x0257509a, 0x00f7aeb8, 0x3fb27235, 0x3537}}}, + /* 15*16^19*G: */ + {{{0x34937fbe, 0x3f9104dd, 0x051ba6ec, 0x2c13777c, 0x16f546c0, 0x050006be, 0x27d70e0c, 0x28fd89f1, 0x2bab}}, + {{0x173a1df4, 0x0e43955d, 0x0ac81109, 0x0b712c64, 0x0eabc9ec, 0x0ec33649, 0x08b88d78, 0x31d96c88, 0x77e5}}} + }, + { + /* 1*16^20*G: */ + {{{0x0351964c, 0x134f4b79, 0x35412c1d, 0x1a490ddb, 0x355c0834, 0x2af28615, 0x0c47fae5, 0x3e566f8a, 0x6e29}}, + {{0x163fd88f, 0x062092f5, 0x20bfb631, 0x1903149e, 0x04246def, 0x0bb1b306, 0x332f6505, 0x1767d403, 0x3456}}}, + /* 3*16^20*G: */ + {{{0x0c0e49cc, 0x3e54040e, 0x3c5400d3, 0x08cb6a16, 0x3740ed41, 0x0a237b2e, 0x30f6edd8, 0x352a5e25, 0xd691}}, + {{0x100f4152, 0x342ed307, 0x2d043f2d, 0x16f8740a, 0x3e0c52ac, 0x2ef6d5d8, 0x0f397f7f, 0x39e1d2de, 0x7a79}}}, + /* 5*16^20*G: */ + {{{0x2b9b930a, 0x361dae7c, 0x130f58f3, 0x2c4d4a91, 0x3bbc49de, 0x16df7de9, 0x0d7c5dee, 0x1a11a8b8, 0x2a5d}}, + {{0x3b2caeca, 0x1bfcd17c, 0x22716858, 0x16dcd0d7, 0x04ab58ea, 0x33c0e40f, 0x2476de5c, 0x1f025a1d, 0xdc3d}}}, + /* 7*16^20*G: */ + {{{0x016959ef, 0x29f72f4a, 0x01db59af, 0x1e74159d, 0x275df876, 0x10c504b8, 0x3b5262f0, 0x125a8e26, 0x8764}}, + {{0x20cd5010, 0x180c472f, 0x2f9e3f16, 0x15ab505c, 0x2d961f28, 0x2d049e5b, 0x02ffd9e0, 0x1a758740, 0x599b}}}, + /* 9*16^20*G: */ + {{{0x3aef0f84, 0x0e502738, 0x31c75b96, 0x2ed41aa1, 0x2db8cab0, 0x38feb05e, 0x071b133d, 0x24ef2049, 0x94d3}}, + {{0x378ba7c1, 0x16b986e4, 0x0acf12a8, 0x0fd00994, 0x239a07dd, 0x32f0e1ac, 0x363f21e1, 0x1aad3ad2, 0x5a82}}}, + /* 11*16^20*G: */ + {{{0x2ffed1b7, 0x35155e13, 0x24aa3b4e, 0x36f44995, 0x34bd2ee2, 0x1425c0b4, 0x24e2dd17, 0x2d682227, 0x4a72}}, + {{0x1601dc5f, 0x17ca7f62, 0x34d9845b, 0x3992e3b1, 0x08ea9685, 0x0cff011f, 0x120e2c8c, 0x39ba9287, 0x3531}}}, + /* 13*16^20*G: */ + {{{0x10467317, 0x0810fc97, 0x0d9186a0, 0x10771076, 0x1e790091, 0x199bcbeb, 0x31e15a78, 0x073f168d, 0xd7f0}}, + {{0x0f7d014e, 0x32e55f57, 0x17fbd895, 0x2805d0da, 0x15ef5728, 0x0d8501b0, 0x26c26ec7, 0x2ef661dc, 0x888d}}}, + /* 15*16^20*G: */ + {{{0x3dea02c1, 0x2f5d6429, 0x374087c3, 0x3eee6df1, 0x231206e4, 0x02fe7647, 0x0371bbe8, 0x282e7ddf, 0x7e50}}, + {{0x2d45c201, 0x0f251b7f, 0x18e1b283, 0x08e4d3c5, 0x0b951774, 0x31bc776e, 0x3e29c616, 0x174f1383, 0xc340}}} + }, + { + /* 1*16^21*G: */ + {{{0x0cb71280, 0x229f5044, 0x04563112, 0x1070966a, 0x2f458ec1, 0x3cbbc1e5, 0x3eed9c00, 0x1aa7acaf, 0xff04}}, + {{0x1ec33919, 0x3b0c9c7d, 0x128487a7, 0x0adb9baf, 0x0cfcc901, 0x07b76f75, 0x13a170a0, 0x156b3025, 0x432f}}}, + /* 3*16^21*G: */ + {{{0x33ca3ce3, 0x3c9e0aa8, 0x36a77e25, 0x0ac6196a, 0x12231fef, 0x16f07d4c, 0x3dcd31a9, 0x31174534, 0xf717}}, + {{0x10ed88e9, 0x2253336d, 0x0176df06, 0x14f8af77, 0x2dee55af, 0x2d53b42a, 0x1512dca9, 0x101da326, 0x422c}}}, + /* 5*16^21*G: */ + {{{0x1b28cd88, 0x0da10c35, 0x2a9bd9ac, 0x23825d40, 0x11b32c73, 0x3ad589fe, 0x30b20c2f, 0x1a6d3ccd, 0x60e2}}, + {{0x2be2066c, 0x0a6ea290, 0x2c846b0e, 0x11584e31, 0x28df7602, 0x0846225c, 0x1f0a9609, 0x05d6995e, 0xfe00}}}, + /* 7*16^21*G: */ + {{{0x061cc594, 0x14ec64ca, 0x0d0536b1, 0x12f745c1, 0x34685596, 0x16e817f2, 0x399490aa, 0x25e8799c, 0x7992}}, + {{0x0f8d309e, 0x3a444248, 0x3ac6e909, 0x36a1ab82, 0x1fe50127, 0x1a4461e2, 0x3c9b0e10, 0x3c633548, 0x132f}}}, + /* 9*16^21*G: */ + {{{0x172d0aba, 0x32311e89, 0x37e1b16d, 0x34642b71, 0x01241dd8, 0x383bad54, 0x2807079e, 0x3a53bf90, 0x2d9b}}, + {{0x31fa0876, 0x23dcc7ec, 0x0b710e6f, 0x34719e62, 0x19d91bba, 0x3be4d2d8, 0x098a2295, 0x236d7a7a, 0xa970}}}, + /* 11*16^21*G: */ + {{{0x355e8732, 0x0301ed20, 0x06d1e31e, 0x298bb794, 0x12c243cf, 0x2f194c52, 0x2421660c, 0x00e7b220, 0x2127}}, + {{0x20cacc07, 0x1648d7d1, 0x2d7bd68d, 0x24fcfcee, 0x3f0a5cd6, 0x12e76eed, 0x235aa019, 0x271bc8eb, 0x8521}}}, + /* 13*16^21*G: */ + {{{0x32083347, 0x0244d033, 0x31a53226, 0x06b8f99d, 0x02b42b9e, 0x343d6ae8, 0x0e0eb97a, 0x2d52caf6, 0xfab5}}, + {{0x3d38fd2f, 0x33327360, 0x2a69afa9, 0x178de985, 0x0a3eafc0, 0x1eabc898, 0x141503c8, 0x3445861b, 0x5758}}}, + /* 15*16^21*G: */ + {{{0x3f572554, 0x3d9c9853, 0x0f4dab73, 0x210b91c6, 0x3ea56ff3, 0x0259dc2d, 0x31fca579, 0x09d5c9e5, 0x685d}}, + {{0x20979e03, 0x1c6bdb42, 0x0f4cca4b, 0x22aa8ab0, 0x20377cc5, 0x0e720107, 0x345fc06e, 0x2270882a, 0xa82f}}} + }, + { + /* 1*16^22*G: */ + {{{0x05852e50, 0x1f42c933, 0x3570cc5c, 0x0b1f98f3, 0x2e7eff8b, 0x26a88d27, 0x3b058c1f, 0x31f7ffaa, 0xe486}}, + {{0x2ecf107d, 0x1ae8f2b6, 0x392ebd86, 0x1118f58c, 0x11e05a69, 0x2229727d, 0x2a12e9ee, 0x1d7b5581, 0x51fd}}}, + /* 3*16^22*G: */ + {{{0x1c881907, 0x19aa9915, 0x300b1dac, 0x0b219cd6, 0x2e041514, 0x0417319a, 0x3fb7c964, 0x112ee38b, 0x4acf}}, + {{0x363cdafc, 0x249ad15b, 0x0d84b252, 0x0d4acbdf, 0x0a545799, 0x10a16b44, 0x1587b354, 0x2a3f83ff, 0xad99}}}, + /* 5*16^22*G: */ + {{{0x3439383f, 0x0aeb81a5, 0x201a2aa8, 0x3fe958ad, 0x234eec34, 0x2a8a4b20, 0x0a649dd7, 0x08a0d062, 0x4ddf}}, + {{0x23d52337, 0x0cbea060, 0x31f82696, 0x35741144, 0x0c0c6b3d, 0x2eba5f4e, 0x1883d74a, 0x189ec364, 0xe71c}}}, + /* 7*16^22*G: */ + {{{0x1822b4f4, 0x1b722055, 0x065df8f2, 0x0d4ebf3e, 0x3bf39ba5, 0x13a781e5, 0x1879e133, 0x195e44de, 0x58b0}}, + {{0x0c60fbca, 0x181ea084, 0x04e52596, 0x29281dbf, 0x22836c1c, 0x32957c09, 0x22c37027, 0x22a90516, 0x55a9}}}, + /* 9*16^22*G: */ + {{{0x34fe39b0, 0x2caf4430, 0x0b4ded14, 0x0c5cf35d, 0x381f358a, 0x2910708c, 0x33529763, 0x38162992, 0xa345}}, + {{0x2baf79dc, 0x1c25202e, 0x3369df53, 0x231a9d6a, 0x39d949ce, 0x02156ca3, 0x2a70f91f, 0x3569b572, 0x7c6d}}}, + /* 11*16^22*G: */ + {{{0x126695fb, 0x3ef81ee6, 0x03adee13, 0x342ee7f9, 0x16ccb6af, 0x2b2e1d1b, 0x0a2c8201, 0x2fe0c064, 0x3a10}}, + {{0x24eb7e47, 0x1571caca, 0x3d452887, 0x23fa9b10, 0x0a65c5f2, 0x00e121a2, 0x22715762, 0x216cfb06, 0xb5d5}}}, + /* 13*16^22*G: */ + {{{0x3d2c8614, 0x106a3a59, 0x05845962, 0x2c258298, 0x112876a7, 0x33d6b0c2, 0x10433ca5, 0x377eb240, 0x12fb}}, + {{0x18b0b174, 0x01def075, 0x019f495f, 0x109608e7, 0x12cfb54d, 0x36450a33, 0x3806833f, 0x0834a409, 0xa5ff}}}, + /* 15*16^22*G: */ + {{{0x2d9aeeaf, 0x0fdd90c0, 0x05afc865, 0x341e5328, 0x399a3005, 0x2b8e87eb, 0x178777b8, 0x3a1668ae, 0x8bec}}, + {{0x05f9eb5e, 0x168368f2, 0x38980f75, 0x0880e3db, 0x3fc368bb, 0x22442c3b, 0x251fcfbb, 0x0cf13141, 0x35f9}}} + }, + { + /* 1*16^23*G: */ + {{{0x2b519178, 0x12dae3b0, 0x03d1fc58, 0x0ee66629, 0x22ee0ab6, 0x0233e2d7, 0x10430cfe, 0x1fd2ed79, 0xf41d}}, + {{0x0a6a3551, 0x1e859977, 0x119e1f9a, 0x126b30da, 0x282347ab, 0x11b78fea, 0x2f8d6f10, 0x1a6faf66, 0xe6a6}}}, + /* 3*16^23*G: */ + {{{0x1e3501d9, 0x29c4c4f8, 0x361fc8b1, 0x3a0b386e, 0x2d3e611b, 0x0b5a4758, 0x14e7f333, 0x209fb58b, 0xd65f}}, + {{0x2b55759e, 0x2e511b1b, 0x1730be1a, 0x304eab57, 0x2b87fc61, 0x2df29459, 0x290fe537, 0x183f3c26, 0xf24b}}}, + /* 5*16^23*G: */ + {{{0x0f2ed84e, 0x2d8bf890, 0x3e2ea12c, 0x26537cd7, 0x2cc0ade7, 0x1b22d5e0, 0x05c385ee, 0x2d6db7ac, 0x55a9}}, + {{0x146495a3, 0x1e771541, 0x2a0d8f05, 0x3fed35c4, 0x17f43ae8, 0x1d34643b, 0x319ab291, 0x0865ab27, 0xc4f2}}}, + /* 7*16^23*G: */ + {{{0x075495a2, 0x2f4b3e1c, 0x0bc00b29, 0x3787ad92, 0x148bc49f, 0x3b582989, 0x371da1f7, 0x15db71f6, 0x79de}}, + {{0x2aec6fb8, 0x00b231aa, 0x093a7468, 0x053d4259, 0x1c79c683, 0x39b6b91f, 0x06a02785, 0x0f439ac6, 0x3b2d}}}, + /* 9*16^23*G: */ + {{{0x02d1e7bb, 0x3ba4ab32, 0x111964ce, 0x30ffe40d, 0x17e55524, 0x12cda565, 0x004b6e26, 0x138c8589, 0x8fe0}}, + {{0x1a62e84f, 0x29d66b43, 0x3046a8cd, 0x2459191b, 0x0db34e5b, 0x1b3a95ea, 0x2358fe5d, 0x36d408bd, 0x3987}}}, + /* 11*16^23*G: */ + {{{0x29f7c360, 0x00692bb1, 0x08085c21, 0x3f355df9, 0x1224e24e, 0x25298da3, 0x1f8f150a, 0x264255fb, 0x3af4}}, + {{0x287d7a7b, 0x0e770aa9, 0x360895cd, 0x15537589, 0x333c3348, 0x3e1920b9, 0x1d91d531, 0x180c34ec, 0xd170}}}, + /* 13*16^23*G: */ + {{{0x370373be, 0x26948eb9, 0x263d3b53, 0x0f418884, 0x227c4e21, 0x160bcff8, 0x08076c1a, 0x3817188f, 0x31a7}}, + {{0x290950a8, 0x3b5e1e43, 0x1a254308, 0x3a0ae654, 0x23db1e8c, 0x2c2ab8d0, 0x1de67021, 0x0bbcfe34, 0xc23d}}}, + /* 15*16^23*G: */ + {{{0x0b923b45, 0x109843b7, 0x13e24bdb, 0x0ea7effc, 0x198458a3, 0x144d18b7, 0x2d23ed15, 0x199204d5, 0x740a}}, + {{0x11ecaa5f, 0x2304f8e1, 0x3c8480ba, 0x25e64e41, 0x1606cfa8, 0x391e229d, 0x1523f2f4, 0x01230973, 0x7f6d}}} + }, + { + /* 1*16^24*G: */ + {{{0x3512218e, 0x212aa4e5, 0x0ca0141a, 0x29486c1d, 0x22e902e9, 0x202ce862, 0x277a6578, 0x141984a9, 0x4a5b}}, + {{0x0c4f3840, 0x2fab69e9, 0x1e26d9d0, 0x1b6c5506, 0x227d4062, 0x1813ef85, 0x089f1c42, 0x11873ab0, 0xeb13}}}, + /* 3*16^24*G: */ + {{{0x118473fd, 0x0bbd0389, 0x29733915, 0x2e409af1, 0x28a9e3bb, 0x24aae65c, 0x18ba0852, 0x018c8ccc, 0x1064}}, + {{0x385cf805, 0x3e9858b9, 0x021d039a, 0x2f864343, 0x05883ccf, 0x1e0a7996, 0x3a2d8c8e, 0x0ca08ee2, 0x9c68}}}, + /* 5*16^24*G: */ + {{{0x253f30f3, 0x159fbb21, 0x1a238dd3, 0x108fb4bb, 0x083f212b, 0x29043550, 0x327bf5ed, 0x2b63fc17, 0x38c8}}, + {{0x2be9217b, 0x01839d27, 0x159df37a, 0x20fea60a, 0x3d641f65, 0x02595376, 0x0b116f39, 0x185e1db7, 0x83c2}}}, + /* 7*16^24*G: */ + {{{0x36ef1584, 0x10f9a446, 0x3920cbf5, 0x2a68a8e3, 0x35184277, 0x23ef8ff4, 0x0bb09585, 0x232f3a18, 0x6fcb}}, + {{0x1d3110f2, 0x0f27df08, 0x28a4325c, 0x24bdb5a4, 0x30459d59, 0x30208eb0, 0x21d76d54, 0x2a0f62dc, 0xa8f1}}}, + /* 9*16^24*G: */ + {{{0x062255ef, 0x23d44d01, 0x364078ce, 0x35c74d19, 0x05b0ee50, 0x05724379, 0x2e2bd735, 0x342e4fdd, 0x7811}}, + {{0x1be3252e, 0x162fbe6c, 0x2d43768a, 0x07b4144e, 0x385132f5, 0x00ba5006, 0x1ac7a54c, 0x1d8dc2ed, 0x99bb}}}, + /* 11*16^24*G: */ + {{{0x353d2ea7, 0x0f8443c4, 0x3fa86509, 0x3b4208e8, 0x016f2a9e, 0x2dca757e, 0x350ce0c7, 0x0f6512a2, 0xc358}}, + {{0x0b667bbd, 0x2c60fa78, 0x15f1c432, 0x32496994, 0x1fcccdd6, 0x1189fbe2, 0x1e90f596, 0x1eb024e4, 0x5396}}}, + /* 13*16^24*G: */ + {{{0x102e3099, 0x3b77c381, 0x28401658, 0x3c84e998, 0x3ad00d53, 0x03c062ed, 0x2e501f3a, 0x33ca0f37, 0xd591}}, + {{0x055ac5af, 0x0ef09d95, 0x3116fd63, 0x3cbbfe22, 0x0bc5825c, 0x04cc34d4, 0x0e6e44e5, 0x3973f11e, 0x87eb}}}, + /* 15*16^24*G: */ + {{{0x32a940a5, 0x2c995918, 0x014e6b12, 0x10d7ad69, 0x39e8714a, 0x09078693, 0x235c4c01, 0x03584bcc, 0xa0aa}}, + {{0x0b950422, 0x0fe20a9a, 0x3d1bf939, 0x1a473769, 0x181f3e6c, 0x0d33e680, 0x3642819b, 0x03ae9dbd, 0x2234}}} + }, + { + /* 1*16^25*G: */ + {{{0x008e2df0, 0x18a360dc, 0x328e5f76, 0x30ec95d0, 0x3e0f5032, 0x30a77e2e, 0x2b995012, 0x2442f78a, 0x2eb3}}, + {{0x1274eaae, 0x2443313b, 0x0f65f490, 0x1034483b, 0x24999f95, 0x0df4d236, 0x34b3a77d, 0x3008cdd1, 0x3f29}}}, + /* 3*16^25*G: */ + {{{0x282867f0, 0x3c0ae12d, 0x3190a39b, 0x0509b886, 0x0900f0a2, 0x2f45a9e0, 0x07ce22aa, 0x36e23993, 0xf6e9}}, + {{0x0f1861ea, 0x1d6cebc4, 0x170b6234, 0x0106e97e, 0x00d5b127, 0x24eddba3, 0x2ab7481d, 0x1e42deb4, 0x53ca}}}, + /* 5*16^25*G: */ + {{{0x320d6102, 0x2b7410e3, 0x34539409, 0x1b54de28, 0x199a5ef0, 0x3056e6d8, 0x2449d785, 0x36ce1d83, 0xfd1d}}, + {{0x2e003b7c, 0x28299246, 0x1513983d, 0x0f864484, 0x03b70016, 0x287c7de2, 0x0638aeda, 0x2e1ce414, 0xcb54}}}, + /* 7*16^25*G: */ + {{{0x02c77cb7, 0x0fdcd077, 0x2dc15b6f, 0x1b650240, 0x2e698fef, 0x129cf997, 0x1901d9fe, 0x1cf08966, 0x61a2}}, + {{0x1ddb25ed, 0x151847e0, 0x0ae1f748, 0x316b669c, 0x2b0cc9c5, 0x28867d7b, 0x2d3d3f4e, 0x334cd34e, 0x5bba}}}, + /* 9*16^25*G: */ + {{{0x377d8976, 0x266355b8, 0x30f292db, 0x05ce8e38, 0x1d04b55e, 0x00b2608a, 0x201b64cb, 0x23997bdd, 0xcd2e}}, + {{0x0867bc22, 0x05a5bd07, 0x1428c051, 0x03b783cd, 0x06ff68f6, 0x073a3cb5, 0x2a31ffc3, 0x2b4d88d0, 0xf58e}}}, + /* 11*16^25*G: */ + {{{0x2c67c998, 0x026cc1b0, 0x3cf1b866, 0x26c1faa8, 0x304c259a, 0x097aa290, 0x23efb402, 0x07e70e08, 0x9bd6}}, + {{0x28199514, 0x0d02be70, 0x0424b18c, 0x1f6707a4, 0x1450fa92, 0x3c825a5a, 0x06f5c5c8, 0x0102645b, 0x77b2}}}, + /* 13*16^25*G: */ + {{{0x2aafa568, 0x291785ef, 0x01e22766, 0x335ea5dc, 0x17a016b4, 0x389e9044, 0x0777512a, 0x3ad3de5c, 0x7afa}}, + {{0x01c1f2df, 0x3b54e8be, 0x1d390233, 0x0b9a50ca, 0x01365a97, 0x34504d41, 0x3d27d895, 0x39864cfe, 0xc6ef}}}, + /* 15*16^25*G: */ + {{{0x0e59ddeb, 0x1f9c0f94, 0x11e98a8b, 0x0f98a72b, 0x2b0c3b48, 0x36530525, 0x012f9061, 0x00889f89, 0xd9a0}}, + {{0x0f0af5a4, 0x3ce4ffe0, 0x35f18ce5, 0x18aa2f2a, 0x27058185, 0x183e290d, 0x2022c43c, 0x2cbe4ede, 0x975e}}} + }, + { + /* 1*16^26*G: */ + {{{0x3ecca7e0, 0x1ce697a8, 0x343333ec, 0x34b263d9, 0x0d9428a7, 0x3d8cd489, 0x12a0c0fe, 0x3b8f171e, 0x7ef2}}, + {{0x152ac094, 0x00ac8b75, 0x3bd3d203, 0x2c851437, 0x2609db81, 0x19fd4757, 0x0c011a4f, 0x2189cc2b, 0xafb6}}}, + /* 3*16^26*G: */ + {{{0x233f0ffa, 0x0bcd60f6, 0x1807a417, 0x3932b184, 0x19c641ca, 0x1295db27, 0x07acd762, 0x15c9c5a2, 0x3704}}, + {{0x20fa35ac, 0x3fb4ff19, 0x28bf2fc5, 0x2e8fadea, 0x15ff4c57, 0x2ed2ee22, 0x1e74f841, 0x0231869c, 0x5c64}}}, + /* 5*16^26*G: */ + {{{0x32603513, 0x31be6194, 0x14a00953, 0x319371a0, 0x0bb697f6, 0x3aa90b02, 0x0db722d1, 0x1e7950a6, 0xc2a9}}, + {{0x3c3505b9, 0x15d56cb0, 0x01514499, 0x3199b7d2, 0x1bce7e8c, 0x1e02064d, 0x2b5c8542, 0x35d2879b, 0xef9d}}}, + /* 7*16^26*G: */ + {{{0x19fdee3e, 0x191bfec7, 0x0302e01e, 0x07e5dc5b, 0x17afb968, 0x2ec5736c, 0x059e1172, 0x061aac7f, 0xc9f4}}, + {{0x0ced22e7, 0x0799b317, 0x358df4f5, 0x3854c71e, 0x03214344, 0x1cc50ae2, 0x3a3410df, 0x029fcf2c, 0x0942}}}, + /* 9*16^26*G: */ + {{{0x0814f217, 0x032cf99d, 0x356cffaf, 0x368fdee1, 0x3bb6a4a9, 0x280093e0, 0x00256b08, 0x3d56e012, 0x27dc}}, + {{0x0cf2ed4c, 0x13252d62, 0x11fc3bf1, 0x13a3eac6, 0x202a380a, 0x22eac252, 0x15dee0bc, 0x3d53d523, 0xbe18}}}, + /* 11*16^26*G: */ + {{{0x1b9e310c, 0x168a93f5, 0x04cfd4a7, 0x0f396e6e, 0x15918731, 0x3492b0ce, 0x2ea4b9c8, 0x0080ec95, 0x3b8b}}, + {{0x2d19fc9b, 0x25059816, 0x2b305839, 0x3fe012e0, 0x0117a6a8, 0x1db8ddf1, 0x3615bd61, 0x1f13ac0c, 0x9111}}}, + /* 13*16^26*G: */ + {{{0x27615b36, 0x3c7878ae, 0x3f3c15f8, 0x13fc7a31, 0x14c3372a, 0x30901be4, 0x0103a105, 0x0e6316f3, 0xa5e7}}, + {{0x09136d80, 0x3660b8e5, 0x0b613c04, 0x3ff064dc, 0x15f8c547, 0x0e37bca8, 0x0e4ce464, 0x3d63725d, 0x1f3f}}}, + /* 15*16^26*G: */ + {{{0x2d3e10db, 0x2dec10cb, 0x0b87159b, 0x1ccb86b2, 0x2b61fa47, 0x0110ffd3, 0x1532bdee, 0x060d56b2, 0xaad2}}, + {{0x2fa05fb3, 0x0d4d6af5, 0x31cba276, 0x00c9dcac, 0x1f8b4a72, 0x3778a3f5, 0x02e3b3a7, 0x07bbaebe, 0x793b}}} + }, + { + /* 1*16^27*G: */ + {{{0x2c49e853, 0x1c07c243, 0x175e04a6, 0x32d4d4a6, 0x1fa77aa9, 0x009553ad, 0x00aeb578, 0x10590859, 0x0e51}}, + {{0x36405cb2, 0x0db8f44d, 0x0c9ee363, 0x1a0e5064, 0x11030df5, 0x3ad294ea, 0x05469278, 0x073a9964, 0xcf33}}}, + /* 3*16^27*G: */ + {{{0x1dc6afad, 0x1288fc70, 0x1f80f46c, 0x34f648a5, 0x00c6771b, 0x3b497d93, 0x2cf25de8, 0x2819d972, 0x977b}}, + {{0x1d7faa09, 0x358b3714, 0x1da1a154, 0x1d684907, 0x01d9992f, 0x0fea8342, 0x38fa2883, 0x2f10ebb6, 0x1bc3}}}, + /* 5*16^27*G: */ + {{{0x1d81983b, 0x17dd175f, 0x38eab786, 0x0883f40b, 0x3ffacc10, 0x32d81dc7, 0x23abe4c3, 0x0a184a84, 0x3bc3}}, + {{0x11a637b6, 0x3667ca14, 0x3bb848db, 0x0d2216a3, 0x300a7f43, 0x2cc172ab, 0x08a20250, 0x209b7b43, 0xa6b5}}}, + /* 7*16^27*G: */ + {{{0x37c8537b, 0x17ddb07f, 0x01f80617, 0x232b2dd1, 0x396c21ca, 0x2bbf872b, 0x004ac51b, 0x293a3a7b, 0x67cb}}, + {{0x385726da, 0x33ad415c, 0x0403f6e1, 0x37c10fb4, 0x31cc047b, 0x07187cbe, 0x08984a1e, 0x3b7b7a87, 0x5b65}}}, + /* 9*16^27*G: */ + {{{0x0b6a1226, 0x1a08a339, 0x35465393, 0x3e7a722a, 0x28f3922a, 0x1cf5a191, 0x099931a0, 0x23a9b55d, 0xc595}}, + {{0x066961d4, 0x30401a23, 0x22108b91, 0x21db6fae, 0x05bd8296, 0x3865c675, 0x37dd7ecb, 0x2a20bdc3, 0xa031}}}, + /* 11*16^27*G: */ + {{{0x33713a52, 0x1378fe16, 0x03c5417e, 0x31d6e31a, 0x0a5fa025, 0x33030f1d, 0x25ca7c1f, 0x1efe0b90, 0x83f0}}, + {{0x1fb0ffb6, 0x04449cfe, 0x1fb45d2a, 0x2d6dd838, 0x07d3cfca, 0x1e53244b, 0x38bb9049, 0x13c42896, 0xf2ec}}}, + /* 13*16^27*G: */ + {{{0x21ba21b0, 0x2b668244, 0x0c265539, 0x15763480, 0x2e0076d8, 0x1a01a1ba, 0x242d4e6f, 0x2e93e6d6, 0x938d}}, + {{0x0d5b4325, 0x1d366579, 0x32b697c3, 0x3c6efb8f, 0x36b90bcb, 0x2ab6f744, 0x356566e9, 0x302a26bd, 0x48af}}}, + /* 15*16^27*G: */ + {{{0x3f2b24f1, 0x14f92698, 0x3e76bcfb, 0x2bb193d7, 0x349779cf, 0x076ab3ce, 0x031e73a8, 0x226ddb28, 0x7efa}}, + {{0x2f8e4b83, 0x19771752, 0x154a455d, 0x2eb7ceb1, 0x16ab211d, 0x3b488bf0, 0x0aeff78c, 0x3cfb187d, 0xa99f}}} + }, + { + /* 1*16^28*G: */ + {{{0x22f2b734, 0x01a66fe7, 0x101d267f, 0x30eed6d5, 0x16445779, 0x129e1bc4, 0x0c99a063, 0x008a67bb, 0x224a}}, + {{0x11ec7fdf, 0x103d6152, 0x3c7afd08, 0x2dc12d9c, 0x1d7fff07, 0x2822b61c, 0x122b4149, 0x2a34a6db, 0xfa41}}}, + /* 3*16^28*G: */ + {{{0x1d254033, 0x27a4bd1d, 0x2a4707ac, 0x0da0a030, 0x36f24078, 0x2b7e9a22, 0x0ec59fcd, 0x00bb854f, 0xe635}}, + {{0x28f05e3f, 0x3a2aa225, 0x3fcf3607, 0x24568312, 0x09ce482c, 0x13a03c1c, 0x21e11ad7, 0x20dec7d8, 0xa7c5}}}, + /* 5*16^28*G: */ + {{{0x21e08f33, 0x2e5826bf, 0x3982cca2, 0x3f58c772, 0x3000e2b1, 0x2d1714cf, 0x3968712a, 0x37b09cba, 0x5648}}, + {{0x0269f1c9, 0x1bbb66b1, 0x01179512, 0x1caefcb8, 0x37a2693e, 0x23d71935, 0x37043f47, 0x371c1c23, 0x95fd}}}, + /* 7*16^28*G: */ + {{{0x3ab98c43, 0x0ee0802f, 0x23e8aa4e, 0x2e95dd5f, 0x2c8f03c5, 0x14be3b2f, 0x0ed26951, 0x3067cce0, 0x1941}}, + {{0x22abe217, 0x3e884368, 0x0df56398, 0x3d8b4f6e, 0x3b8c53d8, 0x1b6ca923, 0x1b2b6e2b, 0x2e0d1657, 0x8e66}}}, + /* 9*16^28*G: */ + {{{0x02d8c2f4, 0x199c3441, 0x39c0189e, 0x0cc86e7d, 0x0d8a0bd7, 0x1cef78d9, 0x34bd67fa, 0x190c7442, 0xfc58}}, + {{0x3cfd274a, 0x0463223f, 0x3c338b40, 0x38b2c17a, 0x3db4ab29, 0x0f09e79a, 0x2d9564a3, 0x3794b3a2, 0x99fa}}}, + /* 11*16^28*G: */ + {{{0x11ff0f18, 0x0ac1dfc7, 0x149a42d1, 0x382f39c1, 0x32d6c207, 0x3eeb3e6b, 0x0f1dea9b, 0x0ee9ac31, 0xee99}}, + {{0x250782ad, 0x004e1db2, 0x30f2cb18, 0x0d72037d, 0x05bcfeb4, 0x3175633a, 0x0db2c1f6, 0x3536515e, 0xd87f}}}, + /* 13*16^28*G: */ + {{{0x0fdde3fc, 0x11e9fdd5, 0x1628cc9e, 0x2a222781, 0x2f31fbe5, 0x03710694, 0x3e2428da, 0x145eaba7, 0xba49}}, + {{0x2fcb7d01, 0x0fbf48cb, 0x3292caaa, 0x37872078, 0x13359adf, 0x3b90dd80, 0x055950b4, 0x2db872a5, 0xa88f}}}, + /* 15*16^28*G: */ + {{{0x3d14da68, 0x2224a8bd, 0x1d201737, 0x19307e13, 0x3612b54a, 0x0b3e09cd, 0x2f1ba4de, 0x23c5d08a, 0xd339}}, + {{0x15a90e3d, 0x3c1d8c6d, 0x141453a3, 0x31e9e48b, 0x22b020af, 0x094b47a2, 0x13d60eb7, 0x3535347f, 0xa34a}}} + }, + { + /* 1*16^29*G: */ + {{{0x3789b84d, 0x298196b5, 0x1041ce2e, 0x1f57b934, 0x2493fe16, 0x174446d5, 0x34b4ccdb, 0x298515cd, 0x4a89}}, + {{0x018e3ea8, 0x3e6df5fc, 0x0711999e, 0x0b8a018d, 0x2677e6a7, 0x0baa5e7f, 0x00d5c08c, 0x13a1fb52, 0x45b0}}}, + /* 3*16^29*G: */ + {{{0x02e14c34, 0x39dac8dd, 0x33275936, 0x1317af81, 0x1377c983, 0x26cc39e0, 0x0ef92a2a, 0x25922a1c, 0xcc9f}}, + {{0x14be556b, 0x224855ea, 0x28c7e058, 0x2645fc60, 0x2689db29, 0x0598cf6f, 0x0c96f431, 0x3fcb2d7e, 0x829b}}}, + /* 5*16^29*G: */ + {{{0x15de4837, 0x1f79b216, 0x1e5e74e8, 0x10a1b20b, 0x198a758d, 0x1630742b, 0x1041af4f, 0x23687eab, 0x5c61}}, + {{0x234a7dee, 0x02e160ed, 0x02278cac, 0x34d99259, 0x3d9671ec, 0x2038e127, 0x3a19d88b, 0x2445ef3c, 0x4c71}}}, + /* 7*16^29*G: */ + {{{0x16635396, 0x1624d099, 0x28a6c0c2, 0x32b8568d, 0x31c11ef2, 0x178b7799, 0x206a2e58, 0x221aa456, 0xab8a}}, + {{0x3fc92c23, 0x38e3e9a8, 0x3d2d6ad7, 0x0d8160fd, 0x3cd5abb9, 0x23fe0922, 0x04319566, 0x33df1f6a, 0xe773}}}, + /* 9*16^29*G: */ + {{{0x01df49c3, 0x3090f962, 0x1069a35a, 0x3a24219b, 0x15604aa9, 0x1992e2da, 0x1838cdec, 0x32145090, 0x62b7}}, + {{0x36341c21, 0x2f8da03f, 0x07cb5509, 0x2d4ed84e, 0x0922db8f, 0x225aba35, 0x20335594, 0x358854ab, 0xa71e}}}, + /* 11*16^29*G: */ + {{{0x244f47d0, 0x2bc51b8b, 0x09f002f3, 0x167d77a5, 0x1fc9791b, 0x147c21a7, 0x089c5f97, 0x2f6fe917, 0x4897}}, + {{0x0e1320bf, 0x079406ab, 0x0f011958, 0x1b68006a, 0x3b093f52, 0x23b2a505, 0x0138c34e, 0x3083debf, 0xe77d}}}, + /* 13*16^29*G: */ + {{{0x31581bd3, 0x186f3a6d, 0x2190786e, 0x3e8c637d, 0x322f2ecb, 0x0781ef69, 0x06576c45, 0x3f2d5592, 0xeb1c}}, + {{0x1cd98a09, 0x2f3a3661, 0x1bd1a645, 0x273cc671, 0x0d6e3cb3, 0x10017af9, 0x14d20504, 0x339d5c7e, 0xfd47}}}, + /* 15*16^29*G: */ + {{{0x273a3111, 0x0048af6d, 0x34c818f9, 0x2e0b905e, 0x2576a018, 0x152b0b9c, 0x21e09c0d, 0x22eef923, 0xa1fd}}, + {{0x38c704ef, 0x221f9942, 0x3d51169b, 0x3b12516f, 0x0916c0c7, 0x1df81ef0, 0x308569bd, 0x17628d28, 0xad21}}} + }, + { + /* 1*16^30*G: */ + {{{0x32bd05a0, 0x10e32129, 0x31fc80d3, 0x208cdf42, 0x2d1f90ba, 0x0be657cd, 0x1885cedc, 0x248d8e8c, 0xe5e8}}, + {{0x21a69f5d, 0x24db78af, 0x0d099aec, 0x1ce656e7, 0x1b5c3eca, 0x07ac079e, 0x387d2130, 0x27793686, 0x7743}}}, + /* 3*16^30*G: */ + {{{0x01467d6b, 0x3c254a04, 0x2a24b514, 0x1f5c4a54, 0x2cf1d835, 0x06184590, 0x1ccf5d10, 0x24f7e50d, 0x5d23}}, + {{0x31bc5458, 0x1f19cf1a, 0x10473a80, 0x29c1e9d4, 0x1af46d72, 0x2f616cb5, 0x10f7d7ac, 0x18fc98ff, 0xe66e}}}, + /* 5*16^30*G: */ + {{{0x1d159f7a, 0x02c7a4f2, 0x242e590f, 0x3e4ea73c, 0x3f873fec, 0x33ecaf4b, 0x3893f3ad, 0x15e94eaa, 0x4536}}, + {{0x0a02fb78, 0x2708adc2, 0x01dda5d9, 0x2526f53a, 0x01c7286f, 0x3bc244e8, 0x23dc5da2, 0x2bbfe200, 0xbfb5}}}, + /* 7*16^30*G: */ + {{{0x146cb42a, 0x07b7b7cf, 0x32390933, 0x014a14e9, 0x3d73e7bc, 0x12b7aa84, 0x04c464d1, 0x1532c1ec, 0x435b}}, + {{0x1af72dd0, 0x1f8937b7, 0x33949a6b, 0x37131e50, 0x20585d5e, 0x12953307, 0x18a1a49f, 0x300c791c, 0xd726}}}, + /* 9*16^30*G: */ + {{{0x1d2fc263, 0x25f6506c, 0x365d57ba, 0x33e04f96, 0x13da0e89, 0x2f11f138, 0x2dd7e19f, 0x2e067853, 0x1805}}, + {{0x30870ec7, 0x1991c2d3, 0x151ecaf2, 0x2306be39, 0x0b31489c, 0x236aa1af, 0x38171585, 0x190a0250, 0x101f}}}, + /* 11*16^30*G: */ + {{{0x0076d1df, 0x28ac6dc3, 0x27fa1b39, 0x07882050, 0x375f45f4, 0x05ea28a9, 0x3194f406, 0x2bd0d9b4, 0xc73a}}, + {{0x25ad6605, 0x09e7545b, 0x1893720d, 0x16d5e947, 0x3cdcfef7, 0x3806f8ee, 0x3916ef9c, 0x3b1a7b33, 0x9201}}}, + /* 13*16^30*G: */ + {{{0x05a745c7, 0x0da0fde6, 0x17eac07d, 0x2289ce30, 0x1d52c1bc, 0x226dabd8, 0x036d2771, 0x3ba3df57, 0xe3dd}}, + {{0x378efcc2, 0x0e7c2501, 0x3d027b1a, 0x0a30bc5e, 0x3bd8f47c, 0x146e1aa9, 0x32b871be, 0x2674e464, 0x4871}}}, + /* 15*16^30*G: */ + {{{0x0d4170b3, 0x131ccfa1, 0x03a3587f, 0x051055bf, 0x00a1d540, 0x22a8461b, 0x1f1e5af6, 0x2377080d, 0x45c7}}, + {{0x111faa1d, 0x1bbe8fb5, 0x020cc731, 0x2c119819, 0x3b3a512c, 0x06a74513, 0x15c0cb0e, 0x265188e3, 0x11af}}} + }, + { + /* 1*16^31*G: */ + {{{0x3ab5c2cf, 0x055e664b, 0x3b084de2, 0x04bc3087, 0x3a90a453, 0x1d1d0413, 0x21f5071e, 0x1f90c788, 0xe410}}, + {{0x2b955c2b, 0x00a100fc, 0x37b2410d, 0x1e24b73f, 0x1c2b323c, 0x2319a1d0, 0x01c9a394, 0x0479b3dc, 0x1e5f}}}, + /* 3*16^31*G: */ + {{{0x09b67b7e, 0x2ed6d8f0, 0x11c3d485, 0x1adecae4, 0x3c114276, 0x3e5c077a, 0x39f7daac, 0x26997b85, 0x85df}}, + {{0x030a36e3, 0x22ce1a7a, 0x3bc6ea58, 0x3ea52747, 0x0e297386, 0x2df57bfc, 0x36308bb6, 0x2dea8e6b, 0xa6b4}}}, + /* 5*16^31*G: */ + {{{0x0b3510d3, 0x09f3f798, 0x0a1d6e41, 0x34c599c1, 0x2d292885, 0x22861970, 0x3cd08a8d, 0x24ff9fe7, 0x23c4}}, + {{0x3ae89a47, 0x0d18bb10, 0x2b9dbd71, 0x2678d789, 0x3fe6d8f7, 0x1d76793b, 0x014230c2, 0x15aa790d, 0xadf4}}}, + /* 7*16^31*G: */ + {{{0x0b49a71f, 0x331a4602, 0x0227c39a, 0x0dbadb19, 0x3235ddac, 0x264faeab, 0x1d0edde5, 0x1b42cc53, 0x9440}}, + {{0x10b249a9, 0x1c706513, 0x263cf944, 0x389c9872, 0x2fe897d0, 0x01f24241, 0x1f179cd2, 0x39dfa193, 0x61aa}}}, + /* 9*16^31*G: */ + {{{0x20e50c32, 0x17378cf1, 0x0c6873fe, 0x3c425cba, 0x2e8d3877, 0x04db7d6f, 0x06c14337, 0x2fd0f7a2, 0x3c2e}}, + {{0x0a93c124, 0x38be245f, 0x2e8c9989, 0x0b4230e6, 0x2e28e7be, 0x16e4f480, 0x0399c652, 0x3669b17a, 0xa703}}}, + /* 11*16^31*G: */ + {{{0x03a2355a, 0x020f677b, 0x06049907, 0x1946fcd7, 0x055f1299, 0x0796e27b, 0x00eb9f39, 0x0db5c9e5, 0x9875}}, + {{0x1bd05276, 0x031d7130, 0x03adccdf, 0x17db1f1a, 0x257b48b8, 0x02c70527, 0x1117243e, 0x26b59d3c, 0x12f1}}}, + /* 13*16^31*G: */ + {{{0x12f3ec22, 0x03c151f1, 0x1a8f8a6b, 0x3e1b73dc, 0x32ddddd1, 0x34e2c5fb, 0x04468f19, 0x2b102693, 0xd515}}, + {{0x25a2863b, 0x28518bac, 0x31b806ec, 0x355f7c00, 0x12bd464c, 0x17921001, 0x09b2e1ea, 0x12050891, 0x51c0}}}, + /* 15*16^31*G: */ + {{{0x1971c857, 0x16687a69, 0x3e6093fa, 0x32679b6a, 0x21cf3dde, 0x14f30e2d, 0x1b0bae24, 0x27526179, 0x070b}}, + {{0x0ac8dfc1, 0x3e72d8f7, 0x05461aaf, 0x2a0f687b, 0x373cfb33, 0x2042b918, 0x3625086b, 0x1186ffd2, 0xed80}}} + }, + { + /* 1*16^32*G: */ + {{{0x1789bd85, 0x1f213f27, 0x297eac35, 0x0d7fdf70, 0x06766efc, 0x20bf5623, 0x35e67fb9, 0x1ce6fbb6, 0x447d}}, + {{0x32e25b32, 0x31f8cf25, 0x3fae5000, 0x0d26e569, 0x0aaff73d, 0x3a7654e9, 0x131eee12, 0x096ae0d0, 0x2d48}}}, + /* 3*16^32*G: */ + {{{0x1ea6db68, 0x0f86663b, 0x02632c27, 0x3eb61582, 0x1ef4f6dd, 0x0537e597, 0x2017f58b, 0x14cf80f2, 0xf8b6}}, + {{0x2e760da9, 0x26f496c2, 0x05ca0ed6, 0x2f5c3767, 0x2a3ec66b, 0x11b76942, 0x054862f0, 0x13bd7b11, 0xc30f}}}, + /* 5*16^32*G: */ + {{{0x3924e753, 0x1b5753af, 0x0f8727c6, 0x005cc1cb, 0x2dfb755f, 0x3bc61ca7, 0x2847c548, 0x2274d560, 0xf352}}, + {{0x2b13a20c, 0x2916d70b, 0x12d0f04a, 0x18bf15ca, 0x0e1bd8c5, 0x3c2286d4, 0x013fb93d, 0x1e07b17b, 0x75c1}}}, + /* 7*16^32*G: */ + {{{0x3018017e, 0x0e572d9c, 0x2df23d72, 0x0507fff5, 0x334e01af, 0x10617ed9, 0x01716483, 0x1add3691, 0xcfd0}}, + {{0x0e0dff50, 0x02b9ef93, 0x3779777a, 0x0c0c1e1a, 0x1a795000, 0x0ece561f, 0x3a913810, 0x2dea6dca, 0xb647}}}, + /* 9*16^32*G: */ + {{{0x392db860, 0x13206415, 0x29a247b0, 0x0224a20c, 0x15dbe981, 0x0b5b423c, 0x1dcd1151, 0x39d312b5, 0x0755}}, + {{0x20d09849, 0x3598036e, 0x3c2777a7, 0x24dd1933, 0x015bc2b2, 0x26cb608e, 0x19e4dd24, 0x2be9d4eb, 0xfe16}}}, + /* 11*16^32*G: */ + {{{0x2a26ba6b, 0x27bda557, 0x2da12c3a, 0x0b28a925, 0x30bbdedd, 0x043035fa, 0x2c96968a, 0x2a1330dc, 0x88fb}}, + {{0x244972f8, 0x01051e07, 0x00cfdce8, 0x12a78a38, 0x14788d48, 0x1b6916d4, 0x1be0fd26, 0x3bd9274e, 0x512a}}}, + /* 13*16^32*G: */ + {{{0x14720cab, 0x2712290a, 0x339b17e3, 0x07a97505, 0x1c6f2c1a, 0x03db9d55, 0x15beb8e5, 0x2b32fb01, 0xe1a0}}, + {{0x34b185c9, 0x1b514fd5, 0x080254ea, 0x128a9c74, 0x2ebcbf08, 0x1be0c1df, 0x0c854183, 0x1a3edfa6, 0xe079}}}, + /* 15*16^32*G: */ + {{{0x2c26c42a, 0x2a0a3f7f, 0x2b11bb62, 0x26fedf91, 0x27e6a024, 0x2cd624c7, 0x33c7e50d, 0x0ee1b9a9, 0x0ae9}}, + {{0x39f808ca, 0x0418cd0e, 0x1aadb649, 0x228e7bbd, 0x220b3727, 0x0b8fb707, 0x07e13a94, 0x3db7451e, 0x7028}}} + }, + { + /* 1*16^33*G: */ + {{{0x137de736, 0x3af62eb0, 0x288ce241, 0x3e355861, 0x1ec18ea2, 0x1d50ae33, 0x0cf3e893, 0x38c52527, 0x9022}}, + {{0x04c42ecc, 0x13bd7021, 0x0ea7657f, 0x124d9b11, 0x26ce087f, 0x02ec1148, 0x0a39466d, 0x1793ca41, 0x2fae}}}, + /* 3*16^33*G: */ + {{{0x109b01f5, 0x05c1b2e3, 0x273c0519, 0x0fcd460c, 0x37857af7, 0x3cb4fc6b, 0x3e945fb0, 0x1cb8c1db, 0x6e58}}, + {{0x2bcd5fde, 0x0c1d6366, 0x09a85a7c, 0x0c5e7538, 0x3ef0ebc1, 0x30752bce, 0x3717180c, 0x300bb235, 0x4213}}}, + /* 5*16^33*G: */ + {{{0x2fe45b1f, 0x14e6dd1f, 0x26168c2b, 0x34557ecb, 0x17df827b, 0x3478d130, 0x23f504af, 0x082c6976, 0x2922}}, + {{0x134bb026, 0x3f902e2d, 0x0dd41045, 0x30d10c13, 0x298d7ff7, 0x31e57feb, 0x175aee37, 0x2814cafc, 0xe316}}}, + /* 7*16^33*G: */ + {{{0x23abd540, 0x3a14198a, 0x3166de43, 0x20101952, 0x093a340e, 0x093e1c84, 0x04f0ac32, 0x385201e9, 0x3644}}, + {{0x155da631, 0x071bf873, 0x26fa14de, 0x05df3b69, 0x21e29300, 0x0a14c27e, 0x2797611c, 0x245436f0, 0xec5a}}}, + /* 9*16^33*G: */ + {{{0x09142ccb, 0x28bf487a, 0x287ede31, 0x248296b1, 0x3bb4824c, 0x2ce3d264, 0x0d838e55, 0x1f6b85ff, 0xedfe}}, + {{0x2c593d75, 0x2e5474c6, 0x151142eb, 0x2910ada7, 0x15beb81d, 0x1574ad3d, 0x1af21618, 0x24848b83, 0xc886}}}, + /* 11*16^33*G: */ + {{{0x0a41b208, 0x0f69c719, 0x2e27000f, 0x3dd1d737, 0x2a0de8e7, 0x05009af3, 0x1a695987, 0x25a2d016, 0x5311}}, + {{0x048e4b69, 0x24787e78, 0x036877f6, 0x0f077009, 0x33da113b, 0x196078ce, 0x22978a6c, 0x1ccacf70, 0xb78d}}}, + /* 13*16^33*G: */ + {{{0x095daae7, 0x0f406d71, 0x07033bcb, 0x11b9bb1f, 0x20e1d5af, 0x08afdbd5, 0x3a594f7a, 0x347c8bfe, 0xf65d}}, + {{0x02556738, 0x35396a67, 0x2acd9b28, 0x018603e7, 0x3c4cd0eb, 0x1bf98df3, 0x366e820e, 0x2e083386, 0x9d71}}}, + /* 15*16^33*G: */ + {{{0x3afcf1ee, 0x2fbf0578, 0x2069a11a, 0x3eaa011c, 0x2807c60a, 0x2fd202aa, 0x2e248b41, 0x039fb732, 0xa667}}, + {{0x20c67fc8, 0x1e21c2af, 0x13cf38a3, 0x3ce62472, 0x17ac131e, 0x17dcbd25, 0x1c2f3a39, 0x05324e94, 0xa7fd}}} + }, + { + /* 1*16^34*G: */ + {{{0x04cd3397, 0x10451705, 0x1515eb57, 0x0d304186, 0x156deddc, 0x21b3cad4, 0x1a723893, 0x3fc1067b, 0x73ba}}, + {{0x1adcb8e4, 0x07bca84e, 0x02613494, 0x27be4b3e, 0x0f825e77, 0x0347a306, 0x3ac5f6a0, 0x3798d25d, 0x1e97}}}, + /* 3*16^34*G: */ + {{{0x161fb913, 0x3ac3e548, 0x2d312977, 0x04091855, 0x3ed04e3e, 0x0e237912, 0x20a18344, 0x0cc30cf9, 0x45f8}}, + {{0x0c15c3bc, 0x035205f0, 0x2fc33737, 0x1b421e7d, 0x3a7760f0, 0x3a01db62, 0x2906ef80, 0x33db6ff5, 0xc212}}}, + /* 5*16^34*G: */ + {{{0x2e393654, 0x2bbe5a47, 0x3edd7c75, 0x1752f87c, 0x0d599196, 0x1680722f, 0x3bdab65f, 0x37126b35, 0x5544}}, + {{0x0f53206f, 0x0d842efe, 0x3d58e732, 0x07bfa5c0, 0x13519224, 0x3016d6e2, 0x3fd4ac04, 0x21625421, 0xed3e}}}, + /* 7*16^34*G: */ + {{{0x28a15dfd, 0x0fcd6650, 0x1fa9e551, 0x076eb009, 0x22f69574, 0x34bb556b, 0x2e7734b3, 0x2de41867, 0x2757}}, + {{0x3042c341, 0x323a1033, 0x0a7156df, 0x1a25e28f, 0x15500d17, 0x25d484f3, 0x2b12e5cc, 0x34b55530, 0xdf46}}}, + /* 9*16^34*G: */ + {{{0x3f840a5b, 0x3fb7d09a, 0x3ad4984e, 0x232b6974, 0x143ccd14, 0x10873304, 0x22bc8d98, 0x10df7943, 0xe872}}, + {{0x1377e86a, 0x21396154, 0x1396464b, 0x0e8d1b3e, 0x248bf5ac, 0x2f247d98, 0x29616593, 0x2f22449c, 0xf984}}}, + /* 11*16^34*G: */ + {{{0x336afd6a, 0x255aa6e2, 0x1781e3d4, 0x187f1428, 0x33334a92, 0x3bdb579b, 0x375c0392, 0x372ae935, 0xc56c}}, + {{0x33f87c26, 0x1821afbb, 0x28cc723e, 0x3d20ec95, 0x194ef566, 0x3b7ac5fd, 0x2b070cd2, 0x15b8bce1, 0xd160}}}, + /* 13*16^34*G: */ + {{{0x2cfd2cd0, 0x36b66034, 0x19c0c131, 0x2504cd10, 0x08abb123, 0x34a160f9, 0x3f2869cf, 0x399ce3cf, 0xd3d6}}, + {{0x394ae2dc, 0x315e71dd, 0x2f6f8f14, 0x07e95a30, 0x3de59b00, 0x36a3fdcd, 0x19b68536, 0x23d7f345, 0xff44}}}, + /* 15*16^34*G: */ + {{{0x1ab7a64c, 0x25622157, 0x209ab7a0, 0x14235a8e, 0x37d40656, 0x04cb5c88, 0x05c07b03, 0x1de215b9, 0x88f9}}, + {{0x1575f103, 0x017a6384, 0x16d2673a, 0x30c02488, 0x169e5836, 0x0c6bc95e, 0x15c74345, 0x173751ad, 0x4a74}}} + }, + { + /* 1*16^35*G: */ + {{{0x1fa4e33c, 0x38b97ecc, 0x3098cb30, 0x20efb1e2, 0x36fb9826, 0x1111b0a5, 0x025bbc97, 0x11ae4693, 0x9cf6}}, + {{0x0e0d4563, 0x27117818, 0x3c160321, 0x081609fa, 0x021f319e, 0x0238962e, 0x25a891e4, 0x1893707d, 0x37b0}}}, + /* 3*16^35*G: */ + {{{0x06bf1e67, 0x262d8633, 0x25caf63e, 0x1599d27f, 0x364e0f4c, 0x2994e09d, 0x364999d7, 0x10f78546, 0x83cb}}, + {{0x099acc97, 0x09fba2cc, 0x1d1169ea, 0x1d108b2f, 0x0418f828, 0x0601b989, 0x0f6f8efb, 0x232892e6, 0xbce2}}}, + /* 5*16^35*G: */ + {{{0x1c0f057e, 0x0c2b5d23, 0x1d53dd82, 0x3a18a1c0, 0x25022484, 0x103f0578, 0x2b08c033, 0x2cf95833, 0x3ff3}}, + {{0x2817965e, 0x3507df6a, 0x07017622, 0x0408dbb1, 0x067843a0, 0x3f45c15e, 0x2578f6f7, 0x2b5bceed, 0x7f17}}}, + /* 7*16^35*G: */ + {{{0x325e69f1, 0x14452d00, 0x022bcb51, 0x19ea3cb5, 0x16af9963, 0x067785cf, 0x3d83fdda, 0x36cb763f, 0x6e9e}}, + {{0x002b7e9b, 0x08385f8d, 0x19f281b7, 0x1c9d151e, 0x33bff61c, 0x155aad97, 0x3954eab3, 0x0885b3bf, 0xc082}}}, + /* 9*16^35*G: */ + {{{0x2288f038, 0x3c94bd9a, 0x35ff820b, 0x21da253a, 0x2c2d32f0, 0x2f06779b, 0x01c4befa, 0x203a0131, 0x5ee2}}, + {{0x36f1ee6e, 0x316aae1a, 0x0e6c6f41, 0x35e0cea6, 0x09eec011, 0x0161bfb3, 0x3e39284c, 0x1a7e519d, 0xbcd9}}}, + /* 11*16^35*G: */ + {{{0x00c708c8, 0x02fcc95b, 0x370a86aa, 0x0d0c13cb, 0x3e288c2c, 0x38d97647, 0x205736df, 0x059b8170, 0xe1f0}}, + {{0x3896ed38, 0x1c635cec, 0x3b5a00ae, 0x1957c8bb, 0x233016fb, 0x118cafa2, 0x03b52044, 0x194fa45b, 0xe647}}}, + /* 13*16^35*G: */ + {{{0x076edefb, 0x383c2729, 0x00e7d5d7, 0x162f6004, 0x39c7badd, 0x086ad0a5, 0x2345c7f1, 0x25a1eafd, 0x2808}}, + {{0x1d1b0ae0, 0x3bd15c8a, 0x20392122, 0x34c6c1ef, 0x0541c44d, 0x3867af64, 0x33191a67, 0x073ccf4e, 0x5d07}}}, + /* 15*16^35*G: */ + {{{0x3344897a, 0x04b666f3, 0x24c269dd, 0x27b4c1d6, 0x25edab7b, 0x217a1490, 0x104cb705, 0x2c378a06, 0xeb15}}, + {{0x25bfe7ee, 0x3677a0f3, 0x17d0b82a, 0x11a62cbe, 0x332f8581, 0x22abe335, 0x26071089, 0x3745a709, 0x096c}}} + }, + { + /* 1*16^36*G: */ + {{{0x123b716d, 0x09beb701, 0x34e1a6b8, 0x08e259bd, 0x18df9e0d, 0x171e4e34, 0x0a534e8a, 0x16f8e2e3, 0xf81f}}, + {{0x12632401, 0x19000bd4, 0x28783304, 0x01d6140e, 0x0e032866, 0x1b4a74e0, 0x306df1d5, 0x124ca707, 0xdc7f}}}, + /* 3*16^36*G: */ + {{{0x39d19d8a, 0x1315a140, 0x1a552158, 0x1049e254, 0x2d490a3b, 0x1bb0d705, 0x286385af, 0x21143ec4, 0xa600}}, + {{0x190d2c4f, 0x36576ecd, 0x326573df, 0x3f8023e9, 0x29ca84f0, 0x1b5179ef, 0x37c72c8f, 0x1e7019e8, 0x7b4b}}}, + /* 5*16^36*G: */ + {{{0x096cac9f, 0x1a61ece5, 0x044de722, 0x38e33a97, 0x2b0e1c59, 0x3025e63f, 0x1f354c64, 0x20ac659f, 0xde53}}, + {{0x2fa473d3, 0x33820bf6, 0x3d841157, 0x38f8a51c, 0x0f9f2bc2, 0x0ec02647, 0x0918562c, 0x2d9e2da7, 0x9c47}}}, + /* 7*16^36*G: */ + {{{0x06807a23, 0x32ca58de, 0x225ff3e7, 0x0008145a, 0x194ec840, 0x12e67544, 0x2a908534, 0x1ec201fc, 0xa722}}, + {{0x14115894, 0x311c660f, 0x328cdc91, 0x2fe055ed, 0x2075abe7, 0x2a11e482, 0x139e845d, 0x1d497517, 0xf550}}}, + /* 9*16^36*G: */ + {{{0x044d14c0, 0x29e5ff08, 0x1a8f35e5, 0x172ad7e8, 0x261d3900, 0x2af9ce8d, 0x04596465, 0x0ba3508d, 0xcd2b}}, + {{0x22496315, 0x1582b3c8, 0x1accecea, 0x36dbc32e, 0x00f671fd, 0x017bb76b, 0x070a24d5, 0x04b7e6c2, 0xf130}}}, + /* 11*16^36*G: */ + {{{0x399a1566, 0x1bd3ac48, 0x3228f696, 0x171956bf, 0x1f9dd8f2, 0x3ef26e0f, 0x1f7eb4ce, 0x3a1323c3, 0x11b2}}, + {{0x1c56bb73, 0x2692cf01, 0x0d809685, 0x12d56103, 0x3405cc82, 0x0b5a61e5, 0x23175d04, 0x1da76f28, 0x6103}}}, + /* 13*16^36*G: */ + {{{0x1ba6f34a, 0x3427aca3, 0x245c6f87, 0x0a1a83f8, 0x19148531, 0x36828fbe, 0x3a070759, 0x064a57ca, 0xfb6d}}, + {{0x2bcf0452, 0x2d7cf208, 0x1685b1f9, 0x3f3e8b72, 0x2791b9ec, 0x223f5312, 0x346dd9e3, 0x0b4a75ef, 0xf29b}}}, + /* 15*16^36*G: */ + {{{0x0a435427, 0x1328b4a8, 0x3e4db507, 0x24042609, 0x106651a6, 0x3d9d9436, 0x013c10aa, 0x27f3040f, 0xff42}}, + {{0x39853824, 0x39411434, 0x23a0da28, 0x16fb94d2, 0x18687620, 0x10272158, 0x2cdb094d, 0x3e59a293, 0x2add}}} + }, + { + /* 1*16^37*G: */ + {{{0x07354b7a, 0x3b671f9e, 0x3915c978, 0x0bb295b0, 0x3cde1d02, 0x1fd18f94, 0x20848239, 0x151d35df, 0x8568}}, + {{0x116e04c6, 0x255100af, 0x3d6fdbd8, 0x2a247707, 0x2f728706, 0x3244eca9, 0x187b6eeb, 0x03ad42fd, 0x20b5}}}, + /* 3*16^37*G: */ + {{{0x3b26165d, 0x3db31fe9, 0x277137ea, 0x04e8857d, 0x0c92dea7, 0x274824bf, 0x23e6549e, 0x1131d4ac, 0x6173}}, + {{0x06b2a286, 0x126ff72e, 0x37171a4c, 0x266b05b8, 0x0220b298, 0x1f442f46, 0x3835a49b, 0x0585e90d, 0xe990}}}, + /* 5*16^37*G: */ + {{{0x10442770, 0x086fdd99, 0x101bad10, 0x063de9b8, 0x00fc2e90, 0x13076a79, 0x36a22da0, 0x00fb957e, 0xf8ac}}, + {{0x1b00c82d, 0x28a193c4, 0x1041d023, 0x1d80afe5, 0x0e6d17a9, 0x1b1d46cd, 0x11e8ea43, 0x23995667, 0x5a35}}}, + /* 7*16^37*G: */ + {{{0x365460de, 0x2f81b61b, 0x2bf77b8f, 0x1cfe342a, 0x0c8ea60c, 0x32f2f8c3, 0x095c66c6, 0x07ed496f, 0x8a73}}, + {{0x3f8dc207, 0x26166877, 0x2508ee3e, 0x219f8f14, 0x304dc435, 0x0a552ffe, 0x363198f5, 0x157178aa, 0x5858}}}, + /* 9*16^37*G: */ + {{{0x351634a5, 0x10aaeb7e, 0x1ed524e6, 0x3e429e0d, 0x17967f3c, 0x29ae80b3, 0x0f224bf0, 0x18184caa, 0xa20b}}, + {{0x3226afad, 0x1b04de57, 0x0d45edf2, 0x1d1d5f8f, 0x3b315bc6, 0x357fa0dc, 0x1b99dad3, 0x33a7da5f, 0x9c43}}}, + /* 11*16^37*G: */ + {{{0x33ba54a8, 0x010c8912, 0x03aa9707, 0x22c98d58, 0x05cc0ab5, 0x0e3b0d3f, 0x16709914, 0x07e4fc49, 0x016f}}, + {{0x264f2889, 0x35f187e9, 0x2a3b4e6e, 0x0ebc9d51, 0x1ce658d9, 0x26c46f92, 0x151576f2, 0x34d04562, 0x08bc}}}, + /* 13*16^37*G: */ + {{{0x27c16d94, 0x3bb924f3, 0x02845fdd, 0x160742a8, 0x0ec31fe2, 0x23f59f33, 0x034788c0, 0x2199c2f4, 0xe615}}, + {{0x314810ab, 0x2d3b466a, 0x3a443bbf, 0x19734791, 0x36f0ee4e, 0x2cae4fd2, 0x124be8c5, 0x00eba79c, 0x65ca}}}, + /* 15*16^37*G: */ + {{{0x13ce728d, 0x35b72999, 0x071cd0bc, 0x33641f8a, 0x085347f4, 0x2822885b, 0x16a26555, 0x1fc2ce35, 0xdcd3}}, + {{0x17cacbcb, 0x35f44da6, 0x29dabeb8, 0x2b34d1b4, 0x06d6f3ca, 0x0ded8acf, 0x24c1872c, 0x36f5df36, 0x6574}}} + }, + { + /* 1*16^38*G: */ + {{{0x12378c16, 0x371b706c, 0x215622ad, 0x0d81d551, 0x39597d9e, 0x2794b5af, 0x33b11b31, 0x2dd6704a, 0x1136}}, + {{0x33488127, 0x27d66f42, 0x351cce37, 0x052a8a39, 0x29ecb296, 0x02af183f, 0x28fdd09f, 0x03f3d145, 0x7dec}}}, + /* 3*16^38*G: */ + {{{0x3b299740, 0x1c39b609, 0x13db1349, 0x03d19f5c, 0x3aad48f4, 0x2b44de4f, 0x14336cc4, 0x0fadc737, 0x5389}}, + {{0x3fff7509, 0x07a9bc6c, 0x1fde8cd5, 0x284cbbc8, 0x35dc8dd8, 0x0738a3a9, 0x1fbd8384, 0x229fa521, 0x2772}}}, + /* 5*16^38*G: */ + {{{0x338000fc, 0x02cf2559, 0x3f03bc13, 0x0789dc1e, 0x3ae5604e, 0x0ddaebc7, 0x0da2757e, 0x3a775d53, 0xdd64}}, + {{0x1df4ac12, 0x3ea87143, 0x11e48f8b, 0x117408ae, 0x0a79ffbe, 0x2278f867, 0x132c96df, 0x24fac30a, 0x4321}}}, + /* 7*16^38*G: */ + {{{0x33878c4a, 0x3e08545c, 0x151c055e, 0x20f40f21, 0x291b21d8, 0x1a718392, 0x3d516f2c, 0x116a1fbf, 0xff98}}, + {{0x3488df68, 0x2e9a11f5, 0x25cfebc6, 0x3ccdd1ad, 0x35e8ddf1, 0x22923b7f, 0x2428f8fd, 0x26bd2938, 0x835b}}}, + /* 9*16^38*G: */ + {{{0x00f51524, 0x32a6e205, 0x3af86fc8, 0x2bada856, 0x1293de5f, 0x19e8c211, 0x1609ce87, 0x04fa2ee4, 0x954e}}, + {{0x05e30a69, 0x27f6cf65, 0x01e7cbde, 0x3ba90c45, 0x1ecbcfa9, 0x31890d1e, 0x24041d93, 0x0d8ffe4a, 0xecc8}}}, + /* 11*16^38*G: */ + {{{0x04f77287, 0x3de6354f, 0x130d9e31, 0x0a54f0da, 0x18049741, 0x35431707, 0x1fb93dfc, 0x1fbdbe90, 0xb221}}, + {{0x24e7b5da, 0x1e8129dc, 0x05e93cb9, 0x02771ce7, 0x38c843d7, 0x3ef3e234, 0x0f3a2b5d, 0x14f8339f, 0xfb51}}}, + /* 13*16^38*G: */ + {{{0x05c723e9, 0x2bd4e5b2, 0x2a781718, 0x25ceeaa6, 0x1d5c351f, 0x31baba45, 0x1bdad122, 0x142c5ede, 0x3c39}}, + {{0x36834763, 0x38e1dd7d, 0x04906ae5, 0x076b2d5f, 0x06a8b0b0, 0x12edfa86, 0x110dbb49, 0x1cd88824, 0xb99b}}}, + /* 15*16^38*G: */ + {{{0x3c18abeb, 0x1c5f5b88, 0x325d62a3, 0x27734641, 0x3aa944d5, 0x3b4be112, 0x21cdad1d, 0x1e8b33e5, 0x803c}}, + {{0x229bfa78, 0x290e6fc3, 0x26721cd6, 0x1f110f0a, 0x0b4409ed, 0x2b3c5a71, 0x2e9286b1, 0x141029e5, 0x83fb}}} + }, + { + /* 1*16^39*G: */ + {{{0x143e832a, 0x31d8bbc6, 0x386df709, 0x3942ac05, 0x09f18e07, 0x15cea096, 0x2a51a90f, 0x3ca2e9f0, 0x0d2b}}, + {{0x1b20d37c, 0x2098ebc5, 0x05514464, 0x3b276e58, 0x34e7ed27, 0x1e842a52, 0x100ac708, 0x0fd0c4ef, 0x0cac}}}, + /* 3*16^39*G: */ + {{{0x112c9666, 0x07ab12f0, 0x1ffcdf36, 0x3e31b0d9, 0x19531b1c, 0x2f30d6df, 0x3f82cfd9, 0x3a17ae59, 0x34e5}}, + {{0x192a3666, 0x168614f2, 0x1e3a526b, 0x11fb58f0, 0x3c46330f, 0x1195d732, 0x1a36b828, 0x1a0c4c88, 0xc0ce}}}, + /* 5*16^39*G: */ + {{{0x11209502, 0x0594af8d, 0x1d92665c, 0x105c8009, 0x19e15459, 0x124fbc24, 0x0d863a6c, 0x18b3167d, 0x7273}}, + {{0x17042b0d, 0x19df474f, 0x32760bbc, 0x234dfe6e, 0x291d20a1, 0x002e30b3, 0x3ab589f1, 0x3d08a6ea, 0x17b0}}}, + /* 7*16^39*G: */ + {{{0x2447f959, 0x1579e4a2, 0x271d3684, 0x11f6aea0, 0x09eee9f9, 0x285312ed, 0x26cec973, 0x3c980152, 0xa0c3}}, + {{0x168b671f, 0x00e74922, 0x0d272c9b, 0x2d550096, 0x228208b1, 0x3e30432d, 0x32c4f382, 0x1cc24392, 0x508c}}}, + /* 9*16^39*G: */ + {{{0x1b37e1d3, 0x087e7c09, 0x0e4de230, 0x1d86f84f, 0x15fd0410, 0x2d0cef90, 0x1ca7a40c, 0x2c8c7de5, 0x7e81}}, + {{0x0155681a, 0x3d7f2899, 0x1c2e0e03, 0x3212fcac, 0x2c7c4e4e, 0x3a25b3b9, 0x3ed13125, 0x1686c3a6, 0xf385}}}, + /* 11*16^39*G: */ + {{{0x16c051a0, 0x125dc57d, 0x35b3e6dc, 0x37ca491b, 0x0f2abddc, 0x1b639b6c, 0x026d84a3, 0x38871f60, 0x8035}}, + {{0x32d0dd12, 0x007aecbe, 0x18b62356, 0x39f718c2, 0x3dd318b3, 0x36f9a0de, 0x22bef375, 0x042912de, 0x0b88}}}, + /* 13*16^39*G: */ + {{{0x3f12c69e, 0x38030c27, 0x1651963c, 0x396bbd62, 0x04fcecaf, 0x2bc00408, 0x0a53306b, 0x0237f586, 0x1969}}, + {{0x1d114831, 0x34cc6410, 0x3fb886b8, 0x2cb8cdc7, 0x21054eb6, 0x3877ab74, 0x16e040be, 0x2fdacbe4, 0x3f65}}}, + /* 15*16^39*G: */ + {{{0x0b89c5ed, 0x1263807f, 0x17a78c7e, 0x2d4c33de, 0x2d0f3577, 0x1b874842, 0x1a2af46e, 0x3f3ae258, 0xdb77}}, + {{0x2d25b46e, 0x27fc71fb, 0x0899afa5, 0x05b1eada, 0x19ad411f, 0x0ce6f932, 0x2e5ceecf, 0x370e1c73, 0x7fd1}}} + }, + { + /* 1*16^40*G: */ + {{{0x37f82f2a, 0x3ba71d77, 0x2fdf43aa, 0x130d61d2, 0x3713269e, 0x08b7d0dc, 0x33617f56, 0x17d59bb1, 0x8a53}}, + {{0x223094b7, 0x17e682b0, 0x08c7669c, 0x394ce193, 0x1a92bfcd, 0x00a06421, 0x08bd737e, 0x30211a2c, 0x0455}}}, + /* 3*16^40*G: */ + {{{0x2b348fa0, 0x2c53c85e, 0x11541ddf, 0x3f891641, 0x24b4bce0, 0x088c8db0, 0x3882dc2a, 0x324f777a, 0x86ea}}, + {{0x0da51cee, 0x3b8e0255, 0x1cfee8a4, 0x09b658d4, 0x2f46716c, 0x0dbe7a35, 0x04d8d5a4, 0x0e14f2ef, 0x948f}}}, + /* 5*16^40*G: */ + {{{0x19222c03, 0x2bd07ff2, 0x3e5e1037, 0x2339dfa1, 0x19f40794, 0x39f5e121, 0x33aae3f5, 0x27aebe7e, 0x8bf0}}, + {{0x2a72bb54, 0x0517dd0b, 0x220e1d4a, 0x27b03877, 0x25ba309c, 0x22c76f9f, 0x27a733b4, 0x2eabf8b8, 0x509c}}}, + /* 7*16^40*G: */ + {{{0x11ae9300, 0x114e8b07, 0x1c48280b, 0x0711c11d, 0x33735b5e, 0x0c2eb68b, 0x30fc6191, 0x0b72edf9, 0xe85e}}, + {{0x1546e25e, 0x0a837f74, 0x38c31bb7, 0x2df86177, 0x3c2707de, 0x29ed6e08, 0x0e0bfc7b, 0x2be9b547, 0x451a}}}, + /* 9*16^40*G: */ + {{{0x05260cb8, 0x14975558, 0x2b2152f2, 0x1bd2a033, 0x27dbf683, 0x009f686e, 0x12f82a3f, 0x2c3c8a32, 0x3f5f}}, + {{0x1852c964, 0x0bed2d10, 0x05ec3327, 0x0fa1d47f, 0x2783f2fa, 0x237854d9, 0x199870e3, 0x0d36b692, 0xc558}}}, + /* 11*16^40*G: */ + {{{0x1a1cd60f, 0x2a91110b, 0x03092ea4, 0x25a62a73, 0x1a002b9f, 0x3b41d2d3, 0x1999657a, 0x1588ac63, 0x3368}}, + {{0x0fd57d67, 0x2fdcdd94, 0x050b8b24, 0x3bd6932f, 0x27af175f, 0x1630037a, 0x07cd9ba8, 0x1427bc49, 0xd42f}}}, + /* 13*16^40*G: */ + {{{0x37576342, 0x014edbae, 0x199222af, 0x0b2220ce, 0x0979d95b, 0x03e76258, 0x00080f7d, 0x3ad7023c, 0x4813}}, + {{0x17376316, 0x130557ae, 0x06a904f6, 0x0b719f54, 0x33524aca, 0x005a1238, 0x24240f66, 0x0ff508ce, 0x0004}}}, + /* 15*16^40*G: */ + {{{0x3f69b2be, 0x3d9c5c77, 0x01111c09, 0x107dd3b7, 0x386e56ba, 0x08b6eeb8, 0x2997af13, 0x3c7e696b, 0x80c3}}, + {{0x0102d2f5, 0x2412e5f1, 0x0b7a8bf8, 0x12dd2cd7, 0x1d5a9bf1, 0x0389d96c, 0x1de85298, 0x08502802, 0x0a93}}} + }, + { + /* 1*16^41*G: */ + {{{0x2476c81d, 0x320dfd3f, 0x1e53d5e9, 0x28c0c3a6, 0x28a366b7, 0x1f349cf6, 0x01a019af, 0x2437f72d, 0xad60}}, + {{0x2e6705dd, 0x062af213, 0x33048df8, 0x0ff70d93, 0x1bd8a839, 0x35d70b31, 0x0c91eacc, 0x3477523d, 0x77b5}}}, + /* 3*16^41*G: */ + {{{0x22725490, 0x2891cdf3, 0x3cb59900, 0x30c90188, 0x09863c4a, 0x36a94cec, 0x1697ca2a, 0x116edc6b, 0xd90b}}, + {{0x2feb1299, 0x03e13e12, 0x3c466ccb, 0x3701effc, 0x38cbd80c, 0x22d5a1cd, 0x3350f09d, 0x24a3b06e, 0x3326}}}, + /* 5*16^41*G: */ + {{{0x3e933668, 0x1dace995, 0x06babf0a, 0x00b6133e, 0x1f06befb, 0x14e4ebe8, 0x13fc7ac0, 0x2485cc48, 0xac25}}, + {{0x32776fb5, 0x1b9dfd9c, 0x29e1e7a1, 0x21906271, 0x18ed7c6f, 0x3b04fbaf, 0x3a8ba850, 0x280e1c36, 0x6c79}}}, + /* 7*16^41*G: */ + {{{0x128de7e3, 0x2985f048, 0x3ea996d9, 0x210ab0ea, 0x3431bf86, 0x083ef69e, 0x1f3a8873, 0x0dd2ba5e, 0x7bc3}}, + {{0x2e6e5e29, 0x1e82ccba, 0x0c0ccf06, 0x3cb6ce6d, 0x0bacbd55, 0x31deb9b9, 0x14e5de00, 0x3c091821, 0xb431}}}, + /* 9*16^41*G: */ + {{{0x035e057d, 0x2b2c8c8e, 0x2d89a5b4, 0x33c436bd, 0x01119329, 0x321cbf0d, 0x202b268b, 0x052514eb, 0xbf9c}}, + {{0x2da20fea, 0x3d592ca0, 0x05c479b6, 0x02e78607, 0x07a54244, 0x14c4fc17, 0x23be0f38, 0x2e27c97c, 0x92ac}}}, + /* 11*16^41*G: */ + {{{0x021d6584, 0x0ab35f08, 0x3b3d9e5d, 0x1c175910, 0x1f014ef2, 0x25f68d6b, 0x04f8a96e, 0x020e6d5e, 0x55bf}}, + {{0x0ed744ea, 0x35593d0a, 0x2e5a5a80, 0x2785080a, 0x3c7dcf08, 0x32fdaea2, 0x21ccf27a, 0x01ccf92d, 0x3d98}}}, + /* 13*16^41*G: */ + {{{0x01068c5e, 0x35a77db9, 0x3e573d0d, 0x117b9b92, 0x15d4872a, 0x2b8539e0, 0x38d519f2, 0x138594cd, 0xfcf2}}, + {{0x27c19d75, 0x187d14fc, 0x014855b7, 0x05da92ca, 0x12e7aee9, 0x1d7886d6, 0x3ffe35c6, 0x2c394cdb, 0x186b}}}, + /* 15*16^41*G: */ + {{{0x220da860, 0x2df657c1, 0x049d1008, 0x0d146a92, 0x191f2f84, 0x36d94d0f, 0x167eca1f, 0x20340bd4, 0x7bc2}}, + {{0x07aac76d, 0x38a44104, 0x0c1632eb, 0x38668bf7, 0x1ee6e0f2, 0x09afe9c1, 0x131e5e26, 0x1b5deeef, 0xb33f}}} + }, + { + /* 1*16^42*G: */ + {{{0x13c4a205, 0x14bcb0da, 0x110a848a, 0x06b7e27d, 0x3929fcde, 0x1955c1d6, 0x1bbc4e46, 0x1b1458c1, 0xb6e0}}, + {{0x1db36d05, 0x0dfd3619, 0x02a9f875, 0x3e65066a, 0x1ed73b63, 0x07c49b9e, 0x323f5c5e, 0x09df086c, 0xbdb4}}}, + /* 3*16^42*G: */ + {{{0x39e27907, 0x0be087db, 0x0d9e4d69, 0x06b52ce2, 0x1fbd6877, 0x257575bf, 0x01c4e6b3, 0x390fe109, 0x0ed9}}, + {{0x2e78c4fb, 0x04fd3d41, 0x0ba1905f, 0x05473fae, 0x120e0ce9, 0x303f63ac, 0x32347f5b, 0x21d2bfda, 0xb5af}}}, + /* 5*16^42*G: */ + {{{0x35b38f54, 0x1b415c94, 0x0af07ce3, 0x0aa18397, 0x3ee1f92e, 0x09a36d23, 0x18f7dc55, 0x390401db, 0x57a7}}, + {{0x245f2809, 0x3e9e0798, 0x107eba75, 0x35db8e6a, 0x02dd21df, 0x32288ef2, 0x0ad24194, 0x03c0f23b, 0xfd7f}}}, + /* 7*16^42*G: */ + {{{0x27a79593, 0x1bfaefe6, 0x25c49794, 0x1e9c9274, 0x0a5cf334, 0x366c9633, 0x35dbef52, 0x26b8bcfb, 0x2479}}, + {{0x10920d55, 0x18e235d7, 0x3eb1398d, 0x250d87e6, 0x23e30099, 0x0f46a74d, 0x07b7b32c, 0x2d498bb2, 0x9436}}}, + /* 9*16^42*G: */ + {{{0x0bf5abdc, 0x0085bad4, 0x10b65066, 0x1b34ebef, 0x0d5d6045, 0x04472c20, 0x07026ed3, 0x05f1a213, 0xf150}}, + {{0x2def85b7, 0x1d778ae2, 0x3b85584b, 0x3719d709, 0x05e232cb, 0x20d078ff, 0x302a8ecd, 0x3bc70b17, 0xdea7}}}, + /* 11*16^42*G: */ + {{{0x3e78e9b1, 0x27c94ac7, 0x2c141e86, 0x1e39b713, 0x12dfcc89, 0x3e0c7dd4, 0x0beaa6e0, 0x3883e26d, 0xe196}}, + {{0x0a77eed7, 0x105d587f, 0x2ed35f44, 0x234044af, 0x32ed9a90, 0x1022f9da, 0x285a62a6, 0x1b617e06, 0xa5d6}}}, + /* 13*16^42*G: */ + {{{0x3b1cb64b, 0x1bb8cf95, 0x18ac3d57, 0x02794958, 0x39ed14d6, 0x1ff35c54, 0x30302f39, 0x3d779b06, 0x7779}}, + {{0x3aba3aab, 0x23863472, 0x0aa9533d, 0x2a0a508f, 0x22e3fae2, 0x2ac4d29e, 0x03ebeadf, 0x108fd1d3, 0x09a8}}}, + /* 15*16^42*G: */ + {{{0x11d1b492, 0x3b6161da, 0x019a6f53, 0x28186308, 0x328ce8df, 0x3db66aba, 0x3a2f11e5, 0x2e52f908, 0x8605}}, + {{0x38ac6598, 0x1c75defd, 0x01e925c5, 0x08d49b52, 0x03d1a8ee, 0x3db83085, 0x35758f3e, 0x184a1f79, 0xa8e5}}} + }, + { + /* 1*16^43*G: */ + {{{0x29aa52df, 0x3357d392, 0x02a627f3, 0x3114ac6d, 0x11ece618, 0x31062766, 0x08bf76db, 0x04725fd8, 0x45a5}}, + {{0x125ec16c, 0x2d4af448, 0x22955ce7, 0x2466c9f4, 0x225ad25a, 0x0ccdff2d, 0x29b6d3fe, 0x03b1dcfa, 0x73be}}}, + /* 3*16^43*G: */ + {{{0x2e75bc7f, 0x159d4fbe, 0x2f7fb1f6, 0x31c5c36d, 0x0d4c7b95, 0x103c485f, 0x393438ef, 0x2b13f9ca, 0x0b57}}, + {{0x0972e9a9, 0x13c5cb74, 0x049fc620, 0x3e5b0390, 0x3e94fab1, 0x30d33e95, 0x1f3b5f28, 0x2fe09dea, 0xceed}}}, + /* 5*16^43*G: */ + {{{0x033125ff, 0x0dd0cf3e, 0x25a81421, 0x1155ec16, 0x1cae9935, 0x1a0b6728, 0x3d148cf4, 0x2cfedb92, 0x1178}}, + {{0x18486abd, 0x203e5c27, 0x0e54d1be, 0x322b7342, 0x310ed10d, 0x3798dfa8, 0x3d95b382, 0x25faa6ea, 0xdfd6}}}, + /* 7*16^43*G: */ + {{{0x3662d955, 0x2cda5733, 0x08ce44f3, 0x1135a16d, 0x27569384, 0x20edfa34, 0x0e907f8a, 0x28209be5, 0x8ac7}}, + {{0x246b3dae, 0x31a8b6f9, 0x16c138db, 0x3d20716f, 0x359ad9e3, 0x1f948d32, 0x3231cc9d, 0x102483cc, 0xc80f}}}, + /* 9*16^43*G: */ + {{{0x288803e5, 0x3361e6b7, 0x13465cb7, 0x06adf383, 0x169e02cc, 0x1fea1c01, 0x1f2111ab, 0x22ca1677, 0xc0f4}}, + {{0x076619ee, 0x1a4c880a, 0x3828edba, 0x0b9381c2, 0x20d7d393, 0x2991c9f9, 0x3ca369c9, 0x09adbe20, 0x3d43}}}, + /* 11*16^43*G: */ + {{{0x1e1f515c, 0x25b59c26, 0x16539afa, 0x2d228c88, 0x37b8c0e2, 0x2723843f, 0x1766da01, 0x1c03c0d4, 0x2ce8}}, + {{0x052eed6e, 0x1464d926, 0x2c3d52c9, 0x2a7734f8, 0x2f5d2ca7, 0x2cbd0bdf, 0x2c4a7bac, 0x27d3ced7, 0x7387}}}, + /* 13*16^43*G: */ + {{{0x24dcf274, 0x16a8ddd7, 0x0acea244, 0x1c801a0b, 0x3cca1d80, 0x386ec3f5, 0x3c109145, 0x1098772d, 0xfac4}}, + {{0x312f0472, 0x0da61803, 0x34594b16, 0x0809f189, 0x2e97bd73, 0x1c8f5753, 0x2a8a87cc, 0x3f718559, 0x9713}}}, + /* 15*16^43*G: */ + {{{0x3dc39d21, 0x2d792daa, 0x09adc682, 0x0dcfaf50, 0x19281368, 0x24790e86, 0x03e00465, 0x398596d0, 0xf891}}, + {{0x05ca579f, 0x1642385f, 0x1460254d, 0x2a5fb13d, 0x1bc43b73, 0x3ae2a38b, 0x1fced18a, 0x14ec4aef, 0x129f}}} + }, + { + /* 1*16^44*G: */ + {{{0x1076f57b, 0x233c6ae6, 0x2cac6072, 0x02e1b8f3, 0x32a53f03, 0x1f8d4073, 0x0c79cb92, 0x06159220, 0x20e1}}, + {{0x2da7afe6, 0x160efb6e, 0x0e1b71e8, 0x383726d0, 0x2de9979f, 0x370f8fed, 0x37ef731b, 0x2cd4ab10, 0xff67}}}, + /* 3*16^44*G: */ + {{{0x0b661da4, 0x1278ebb5, 0x0a84a5c8, 0x02946b19, 0x061a2194, 0x31ff640c, 0x206ce8f7, 0x0a96ee19, 0xffca}}, + {{0x2f9b8a5a, 0x26120d7a, 0x1687f6f8, 0x23e1eb79, 0x346c8c47, 0x33268523, 0x1cdc8a53, 0x2c38cadc, 0xce1c}}}, + /* 5*16^44*G: */ + {{{0x1c8cfd22, 0x32b0784e, 0x236be583, 0x0ac19c6d, 0x2d354a4e, 0x14d45436, 0x116ab636, 0x273b7ff0, 0xff20}}, + {{0x13bc5535, 0x0e26c53a, 0x1684b942, 0x13d2e4b2, 0x0ff1c80d, 0x35074933, 0x10f7e207, 0x3ce5d1a7, 0xad79}}}, + /* 7*16^44*G: */ + {{{0x0f4e983e, 0x201f9616, 0x017f77ce, 0x279bb21c, 0x3b4b156d, 0x0102034c, 0x39ba9586, 0x3c0b42c1, 0x33d5}}, + {{0x11ea37a9, 0x35c36e1e, 0x1630c956, 0x1c6aa496, 0x3ba1eb7a, 0x0f585956, 0x0478473c, 0x169db4e7, 0x01eb}}}, + /* 9*16^44*G: */ + {{{0x21e52a73, 0x1a569e7d, 0x305a1bcb, 0x38c45b25, 0x3b5e65d0, 0x25d366b6, 0x21690a9e, 0x348f6989, 0x8f1b}}, + {{0x2bea8f2e, 0x1f685147, 0x31850a85, 0x0140b992, 0x03eade59, 0x1a790c1d, 0x1a8b8b87, 0x23d8e4eb, 0x4c7a}}}, + /* 11*16^44*G: */ + {{{0x3d2bc078, 0x210bfb0b, 0x1f3ef5a5, 0x281d814a, 0x1880aec4, 0x0a62df6b, 0x237f3ee6, 0x327fbded, 0x963b}}, + {{0x1afb8657, 0x376c8c7d, 0x043a3c27, 0x3b010a3d, 0x00a4f1c5, 0x0f9424a6, 0x2762280a, 0x0e0ff347, 0x7ed3}}}, + /* 13*16^44*G: */ + {{{0x2fb608ad, 0x21c79dba, 0x08fd93a6, 0x20159536, 0x08bc4974, 0x06b772df, 0x1a844e63, 0x1b6b6187, 0x89fe}}, + {{0x064d4dad, 0x00501b9e, 0x0f0a87b6, 0x2a7544f8, 0x25df39ae, 0x15f7fedc, 0x0e8fc87b, 0x09e08c7d, 0x2898}}}, + /* 15*16^44*G: */ + {{{0x19ae4a29, 0x1c62606c, 0x2232a0b0, 0x0bf69ba8, 0x166984df, 0x35eb1384, 0x39759510, 0x011fcef5, 0xc348}}, + {{0x0eb09235, 0x12566b13, 0x149aebf3, 0x08ba67c1, 0x0dae9a84, 0x2a374838, 0x21c5613d, 0x207c815a, 0x5847}}} + }, + { + /* 1*16^45*G: */ + {{{0x19273a8f, 0x34514ba2, 0x14fd54ad, 0x3751e39a, 0x17dac93f, 0x23b1ff7f, 0x2027b031, 0x313e1c8e, 0x5c9c}}, + {{0x1ce80d6e, 0x376b29a5, 0x11acab5a, 0x000d9d68, 0x08af964f, 0x1d6274dc, 0x2d259a82, 0x381e877f, 0x84ef}}}, + /* 3*16^45*G: */ + {{{0x0883e382, 0x32326151, 0x15536f38, 0x1813f3bd, 0x007431d0, 0x0900e548, 0x3d85c5be, 0x3864aef7, 0x5ac8}}, + {{0x1dfeaadc, 0x04dcf66f, 0x14d9d2e5, 0x1dbb284f, 0x163976de, 0x23ffcbc2, 0x28c8039c, 0x3940131e, 0xfcb7}}}, + /* 5*16^45*G: */ + {{{0x2f01a3e8, 0x3290c1df, 0x248094eb, 0x3ad950cb, 0x167362c6, 0x05751383, 0x121182d5, 0x01a62de4, 0x99dc}}, + {{0x00f61114, 0x0a1917f9, 0x3f8f2945, 0x299c0d35, 0x180044b7, 0x2b1c45c7, 0x182bc697, 0x273748ee, 0x67c6}}}, + /* 7*16^45*G: */ + {{{0x0cd535ab, 0x20fdec01, 0x0764dc33, 0x093620fa, 0x0fb9f377, 0x090d5f3f, 0x00616440, 0x3cd86381, 0xabe2}}, + {{0x117b9c1a, 0x01c46cd1, 0x3ac8dd99, 0x379e8630, 0x2df7957f, 0x36fcac80, 0x1b293de0, 0x35932dd5, 0x4f02}}}, + /* 9*16^45*G: */ + {{{0x2909970c, 0x2d2d9acd, 0x1e6e4e0d, 0x0636e966, 0x26099e45, 0x1bec7ddf, 0x1e72137c, 0x3435e30e, 0x227c}}, + {{0x1f809727, 0x21692b8c, 0x2b99ec42, 0x043b0fdf, 0x3f5defa2, 0x1b21d073, 0x1391d87d, 0x39dc7206, 0x2225}}}, + /* 11*16^45*G: */ + {{{0x09e65b59, 0x366b7f26, 0x144ff77c, 0x10408bdf, 0x0d053b7a, 0x3ba4c2a3, 0x1c5b6827, 0x11a082bb, 0x3631}}, + {{0x29b4c2cf, 0x20285909, 0x1c5b6e9c, 0x10f240ed, 0x227fc1c1, 0x09e3e480, 0x172928e8, 0x36d885e2, 0x1d87}}}, + /* 13*16^45*G: */ + {{{0x0d4c2506, 0x05ec562f, 0x19e9faf0, 0x1b1771fc, 0x1d1fec5b, 0x29a33862, 0x318a3e74, 0x35ad9a1a, 0xf65e}}, + {{0x3913dfac, 0x314b7094, 0x0d6542bc, 0x0a3bf0d3, 0x36e7bd41, 0x1770bf4d, 0x3aae8525, 0x2f1a0ca2, 0xd6d0}}}, + /* 15*16^45*G: */ + {{{0x3b47a80b, 0x0793e5d4, 0x02497578, 0x25f16999, 0x2bdba8ff, 0x36709dbe, 0x2135729d, 0x37be847d, 0x66a0}}, + {{0x3f795e8b, 0x3dc657e3, 0x26edd200, 0x0c290a14, 0x2ef474c2, 0x237c9586, 0x2ca41cad, 0x2a9b78de, 0x3e24}}} + }, + { + /* 1*16^46*G: */ + {{{0x28523eb3, 0x1f766acc, 0x16c6c4ae, 0x068e9d55, 0x3dcde335, 0x3061113c, 0x0b5ab46a, 0x353afe2a, 0xbaff}}, + {{0x15acf387, 0x25e0c033, 0x348b6ee1, 0x144733ef, 0x1ac09c24, 0x2a3acde5, 0x15e83003, 0x0f7176f2, 0x0fa9}}}, + /* 3*16^46*G: */ + {{{0x34737641, 0x00266d3b, 0x2c2e13ad, 0x3eb03059, 0x163fb71a, 0x22d448d9, 0x089ed777, 0x11489107, 0x91b4}}, + {{0x2101bbe0, 0x0944aca7, 0x2077d03f, 0x35f7199b, 0x2fb428c9, 0x0c8d6ac0, 0x1a9762c1, 0x18ef4dff, 0x3f44}}}, + /* 5*16^46*G: */ + {{{0x26dd01df, 0x1a8aeae0, 0x38fefb9c, 0x0fbfdd94, 0x28916574, 0x3a9b1f21, 0x1b07aa37, 0x04d77a0b, 0x296d}}, + {{0x2a3a0dc8, 0x25434c82, 0x1e66f604, 0x3ebd8639, 0x0777cadf, 0x1c4a5ddb, 0x145e42b8, 0x13b764b8, 0x1405}}}, + /* 7*16^46*G: */ + {{{0x1650f5dd, 0x19f9bc1b, 0x191b2c8c, 0x3ff84908, 0x1e4a9654, 0x0f0bc7c6, 0x27a318f1, 0x10bce44d, 0x4b09}}, + {{0x3aeddc6d, 0x0ba96f31, 0x0e73a62c, 0x0f19e0b9, 0x13c25f02, 0x17040558, 0x0abc0e05, 0x2aa98d9b, 0x7432}}}, + /* 9*16^46*G: */ + {{{0x04e4a96f, 0x28dd7a3c, 0x1655b147, 0x2218ad0d, 0x12e4af18, 0x3b6e3f13, 0x0c11a833, 0x1de98bfb, 0x0363}}, + {{0x11e08cdb, 0x2ebedf81, 0x30913268, 0x02630850, 0x14626384, 0x0c3155e1, 0x3df838d9, 0x06474d53, 0xa1de}}}, + /* 11*16^46*G: */ + {{{0x279b5a59, 0x107f4f85, 0x269e62a1, 0x087a27ac, 0x183251c6, 0x2fb55c27, 0x1e162bcb, 0x06bdcc3d, 0xa104}}, + {{0x2c5514a3, 0x234ad008, 0x2ac66d9d, 0x0c1a4387, 0x3c2afbfb, 0x194361ce, 0x18b19422, 0x05daaa3d, 0xad42}}}, + /* 13*16^46*G: */ + {{{0x0ddd597b, 0x2ba36c1b, 0x085758de, 0x224c5c33, 0x292007d8, 0x1c6b43e7, 0x25647033, 0x19eb42c7, 0xda21}}, + {{0x3de7fa04, 0x1a05c9f8, 0x04f9f462, 0x378a9485, 0x18ebf6cd, 0x19c03a9e, 0x2ed361ff, 0x24ad8951, 0xa219}}}, + /* 15*16^46*G: */ + {{{0x33f7dbb0, 0x24d2888a, 0x2bf29c09, 0x3b88f709, 0x24f29df4, 0x18ee1c85, 0x2c678bc8, 0x36f08dfd, 0x1c3f}}, + {{0x32e16d32, 0x1932f725, 0x020f8add, 0x01918e00, 0x0b18d41f, 0x3a94e529, 0x29813f0a, 0x03c40de4, 0x3926}}} + }, + { + /* 1*16^47*G: */ + {{{0x3a111101, 0x0d482362, 0x2db3c5f8, 0x27c2c69d, 0x3e4c9647, 0x0a8d3495, 0x2d766ed2, 0x0a8263f3, 0x06ad}}, + {{0x1fb37ef4, 0x069eea75, 0x30e89aec, 0x10a760ad, 0x2b62a0de, 0x13006ee7, 0x05e3559a, 0x22c7163e, 0x2d5b}}}, + /* 3*16^47*G: */ + {{{0x302bef6f, 0x1bf0e11d, 0x131ee437, 0x2b93c611, 0x18d475bb, 0x1e2f59af, 0x3cd7204f, 0x32955b0e, 0xf1a2}}, + {{0x0f6c1ca3, 0x06cb47f6, 0x3d52b401, 0x2d1faa07, 0x020168b0, 0x15505f70, 0x0313edf4, 0x166bc122, 0xb39b}}}, + /* 5*16^47*G: */ + {{{0x20455367, 0x0180a3f2, 0x0d613e08, 0x313cb209, 0x3f1851e6, 0x2405963a, 0x38030ee1, 0x2b527f8e, 0xe924}}, + {{0x28257e92, 0x3f4633e0, 0x3a6752b5, 0x368c6a93, 0x2fbb6f52, 0x0214e4f5, 0x03ed5752, 0x1f65e685, 0xfcc9}}}, + /* 7*16^47*G: */ + {{{0x02f8f1e7, 0x247c24e5, 0x1d1f9e2e, 0x352a9753, 0x3b22f68d, 0x2e4d4417, 0x3026fa00, 0x271f717d, 0xf49d}}, + {{0x114d9972, 0x088a2ac6, 0x24d7a839, 0x2c004f13, 0x14f67901, 0x174ecee6, 0x3acae6ae, 0x175080f8, 0xf558}}}, + /* 9*16^47*G: */ + {{{0x3b219a79, 0x2cea59df, 0x29827a77, 0x1335105f, 0x1189e65c, 0x0f0d55d5, 0x29d48b0e, 0x1340f91a, 0x28b0}}, + {{0x102dbe24, 0x22fdf364, 0x2004be5f, 0x059b33e1, 0x3e206b86, 0x3f95c860, 0x0cf1459c, 0x36a79685, 0xf658}}}, + /* 11*16^47*G: */ + {{{0x17774af9, 0x0a08b671, 0x1460ad8b, 0x05ae9944, 0x2aefb54c, 0x140e4a21, 0x1fe93d68, 0x19af9f30, 0x3f47}}, + {{0x1d4de990, 0x1f35fd93, 0x1b7326ff, 0x2a533f7e, 0x2e5f511c, 0x05e241b9, 0x31cba3ab, 0x0375a9cc, 0xcc81}}}, + /* 13*16^47*G: */ + {{{0x08e57705, 0x21067c79, 0x04d598e7, 0x33adfeb2, 0x2f361721, 0x2b6ad075, 0x0ee791f2, 0x2780b03e, 0xe324}}, + {{0x38caec0c, 0x252c67a0, 0x27384220, 0x065175c5, 0x086b5a50, 0x1de307c9, 0x29507dcb, 0x1961c04d, 0xa666}}}, + /* 15*16^47*G: */ + {{{0x325b93ac, 0x1e2f3abe, 0x187f8d2c, 0x38809441, 0x3bb4e917, 0x279da4f7, 0x3961cbdf, 0x1602f7ed, 0xa689}}, + {{0x2f589aab, 0x28f47135, 0x1c4fd3ae, 0x3c7e05f6, 0x059ff2fc, 0x3cbc057c, 0x0783eaa7, 0x32a52d3c, 0x4657}}} + }, + { + /* 1*16^48*G: */ + {{{0x313728be, 0x33c83fec, 0x3c6b94a6, 0x10e56468, 0x315fc596, 0x1bfe0d10, 0x09276273, 0x259de9e1, 0xa6d3}}, + {{0x0357f5f4, 0x0aeae0cf, 0x284059bf, 0x12a48308, 0x27ecdf82, 0x22eaf4b4, 0x3881666b, 0x211d26c2, 0x674f}}}, + /* 3*16^48*G: */ + {{{0x0f15d864, 0x0152d5a7, 0x1cc8d3cc, 0x01bf71a8, 0x26cf3524, 0x23b39ef8, 0x2db0dafc, 0x19b5f177, 0x07ef}}, + {{0x340907fe, 0x1189509d, 0x0ce4a8b5, 0x11c38ec7, 0x3d505e9f, 0x10314887, 0x1e6a506d, 0x0c976e27, 0x2db3}}}, + /* 5*16^48*G: */ + {{{0x17c7c05e, 0x1a5450f0, 0x0e5416ac, 0x20f2e54b, 0x328c0bb2, 0x0e9cbdd7, 0x1c46014f, 0x1397f01b, 0x82df}}, + {{0x18fff26b, 0x2584f40b, 0x02db300b, 0x057651a1, 0x17cbd1cf, 0x08588448, 0x2420a275, 0x22326325, 0xe4e1}}}, + /* 7*16^48*G: */ + {{{0x140368b0, 0x02b87505, 0x3ee949d8, 0x09308be3, 0x247a6213, 0x396e34e3, 0x30c6a7d9, 0x3f26f04a, 0x261e}}, + {{0x3deb011f, 0x0eb49566, 0x39b5d301, 0x0d02f878, 0x0fff797e, 0x2214b359, 0x2fce9fdc, 0x0ab6f8e1, 0x8a9d}}}, + /* 9*16^48*G: */ + {{{0x15eb8034, 0x040cfa54, 0x2e8ca4af, 0x02ccd7d5, 0x27692df3, 0x29f96767, 0x0279149a, 0x37f5de8b, 0x6d48}}, + {{0x1ab0ce30, 0x21cc21e9, 0x23e8961e, 0x00843a8a, 0x05476308, 0x39e59278, 0x1d12f3d5, 0x1c914597, 0x3cb4}}}, + /* 11*16^48*G: */ + {{{0x140535c8, 0x1450f7f1, 0x08db13eb, 0x3c2958c3, 0x054e6f65, 0x048fed3f, 0x18923a49, 0x30079eee, 0x93a5}}, + {{0x3d59b844, 0x1255d020, 0x35bedffc, 0x28588124, 0x15a5c166, 0x2a10d638, 0x0c2f4c16, 0x03a41260, 0x2d44}}}, + /* 13*16^48*G: */ + {{{0x1e2047ba, 0x0986959a, 0x3b0f652a, 0x11c1265a, 0x167031e5, 0x3683805f, 0x272bbb35, 0x2e4a4584, 0x3fb0}}, + {{0x1db24158, 0x1ffb353b, 0x17009d35, 0x1082b9dc, 0x266dc86c, 0x09887265, 0x3df94ca7, 0x1eb9a085, 0x9d46}}}, + /* 15*16^48*G: */ + {{{0x22df71c1, 0x02f6f6eb, 0x3bb723a0, 0x0c61afab, 0x33e4381c, 0x18eea778, 0x283d5d07, 0x250e7823, 0xdab0}}, + {{0x24c3a1e3, 0x21cd2104, 0x0b44e3bb, 0x258cc329, 0x120b3d6e, 0x2ba1bc83, 0x21cef385, 0x2f079513, 0x763c}}} + }, + { + /* 1*16^49*G: */ + {{{0x0514c6fd, 0x3bbd8bfd, 0x1ab013e6, 0x1a0ed343, 0x3f5936fd, 0x136d5c43, 0x0f4e033d, 0x36a00227, 0xac25}}, + {{0x05830541, 0x02d4e5dc, 0x03bf37a6, 0x0260fa09, 0x1b338c81, 0x36a4c4a8, 0x04c7b883, 0x2766172d, 0xebc6}}}, + /* 3*16^49*G: */ + {{{0x32fd0e3d, 0x065071f8, 0x027ad608, 0x0c793715, 0x165547e6, 0x1d219c78, 0x23c8bb4d, 0x399b126e, 0xeea7}}, + {{0x191d5868, 0x01047da3, 0x019e3cc1, 0x32eb688c, 0x1b7d985a, 0x10fc9efa, 0x09261288, 0x3516e7e2, 0x83fe}}}, + /* 5*16^49*G: */ + {{{0x2ccb63b3, 0x067c53c9, 0x0408e5d1, 0x37ff9b11, 0x03c67b7d, 0x0652cd50, 0x221bdbad, 0x38b4fa4f, 0x9a3d}}, + {{0x3df93fcf, 0x0714ca5d, 0x35822600, 0x300767fb, 0x013c4c49, 0x3c9cdbba, 0x112c8809, 0x26e41844, 0x2f80}}}, + /* 7*16^49*G: */ + {{{0x163f1117, 0x13b28d37, 0x27f6d8be, 0x225bdc2e, 0x3fadaf34, 0x0034c048, 0x392db051, 0x20bd2d4e, 0xa7c3}}, + {{0x1934cb9a, 0x04883178, 0x3c4a68cc, 0x13addbb4, 0x1dcfb5ae, 0x27ddddc1, 0x1bf88045, 0x394459d8, 0x1b91}}}, + /* 9*16^49*G: */ + {{{0x26774a96, 0x02f20716, 0x038e3e85, 0x08c7f646, 0x26f497e8, 0x10eff20e, 0x21213871, 0x2a663361, 0x555a}}, + {{0x06db0e34, 0x35025cb6, 0x0e26fa69, 0x035752f2, 0x10bbb89a, 0x11079c4d, 0x3bc6999d, 0x0a1a3481, 0xb053}}}, + /* 11*16^49*G: */ + {{{0x2f7dac7d, 0x0bdfbbce, 0x12412123, 0x15cae484, 0x37c36916, 0x335e3e35, 0x27ad7b58, 0x0bd6cd22, 0x01a4}}, + {{0x0195e46e, 0x1e2528c6, 0x0cea96b2, 0x0abca4ca, 0x3f921617, 0x1fe552e2, 0x07781349, 0x270e1548, 0x957a}}}, + /* 13*16^49*G: */ + {{{0x202afc36, 0x00ae8750, 0x03071d3e, 0x137bb545, 0x05d3a313, 0x2c27bc6d, 0x1ce3d3a5, 0x3d4dfac1, 0x4b47}}, + {{0x2f8133ff, 0x3a27dda9, 0x25fbda34, 0x16b2fa6c, 0x0df57334, 0x2c1be83a, 0x05f0c2dc, 0x1140e672, 0xf2fc}}}, + /* 15*16^49*G: */ + {{{0x37d17f68, 0x2afcb8f1, 0x38bad86a, 0x056877f2, 0x2e418f79, 0x145bd4da, 0x0e8ced56, 0x3b273149, 0x6b3d}}, + {{0x09232402, 0x3eb9e883, 0x2dccb68c, 0x3caa5aa9, 0x0d5d4747, 0x2606d05b, 0x3d9ef050, 0x0e4dff7b, 0xb865}}} + }, + { + /* 1*16^50*G: */ + {{{0x2fd20bae, 0x17538de8, 0x1b4a8115, 0x00d59cb5, 0x2d343a26, 0x2ee8485d, 0x0fcd9027, 0x143b70ef, 0x2852}}, + {{0x14e0ab97, 0x27791569, 0x1eff323f, 0x26c68b3c, 0x06c1716e, 0x0a12b441, 0x17ea83f7, 0x3021bd2b, 0x7866}}}, + /* 3*16^50*G: */ + {{{0x2636a50b, 0x3221daae, 0x3b75196c, 0x0bbd85aa, 0x38baf65d, 0x1be84bf1, 0x1a75c583, 0x31595175, 0xf1e3}}, + {{0x2b3128b6, 0x3dde453a, 0x22d7a6ed, 0x1fe95db4, 0x25f3136b, 0x0da99fda, 0x2fce76c7, 0x211e9b87, 0x12b8}}}, + /* 5*16^50*G: */ + {{{0x0e583340, 0x05fc4c85, 0x134f3b25, 0x1706dad7, 0x1b228cf4, 0x1f36afea, 0x134a76d8, 0x1ca72078, 0x584d}}, + {{0x34fb24b9, 0x0bdb97a5, 0x094c0707, 0x05dc2999, 0x30affa8f, 0x01f164c0, 0x180abcd3, 0x20291583, 0x2fdd}}}, + /* 7*16^50*G: */ + {{{0x0235809b, 0x0b20fb78, 0x1eb81739, 0x15cb7c2d, 0x383c453c, 0x380a3708, 0x3df7d1e2, 0x2b80320d, 0xbaae}}, + {{0x0154fd62, 0x35876297, 0x1d2e7e5c, 0x170f10a8, 0x09f29983, 0x08c1ef2d, 0x24b80b4a, 0x2220cfcc, 0x3257}}}, + /* 9*16^50*G: */ + {{{0x0d612268, 0x18010b10, 0x25ed016f, 0x33d677c2, 0x14b8b906, 0x0e7be90e, 0x2131a651, 0x3918d830, 0x06c7}}, + {{0x260166a0, 0x32d2d804, 0x02e7098b, 0x2362969e, 0x3453ca23, 0x3f1d738b, 0x1d8cd747, 0x35577dcb, 0xcb6a}}}, + /* 11*16^50*G: */ + {{{0x012fbdc8, 0x350e8d6e, 0x2c0e2a3b, 0x278832a8, 0x11a36db8, 0x0bb31edc, 0x2643e5bc, 0x0c77aaf5, 0x0641}}, + {{0x29f99380, 0x34ffcc26, 0x1fb020a5, 0x0eb89a2c, 0x15759860, 0x0e0364d2, 0x27028f2b, 0x1feb0cb5, 0x882c}}}, + /* 13*16^50*G: */ + {{{0x0bac9f32, 0x17ac0019, 0x1689b067, 0x0e087316, 0x1b640044, 0x1905bf86, 0x1c2378a1, 0x2deb309d, 0x366b}}, + {{0x3c85d47d, 0x0bc3973e, 0x3f0268a4, 0x37394301, 0x21cfc01f, 0x1e0eae35, 0x1af064f0, 0x1edc21e1, 0x7d10}}}, + /* 15*16^50*G: */ + {{{0x06dd27eb, 0x0f2d494a, 0x33b56230, 0x231570de, 0x3e32ecb9, 0x1f438e6e, 0x33c006b2, 0x36c95f31, 0xb767}}, + {{0x0f65dac4, 0x1548691f, 0x0600ed41, 0x2dc02d12, 0x19d85b64, 0x2b2e05ae, 0x229cb5ce, 0x0230c984, 0xdc13}}} + }, + { + /* 1*16^51*G: */ + {{{0x3e07e4f1, 0x1c7ce8a8, 0x0dc267c1, 0x31451f74, 0x38890e1f, 0x37af01fb, 0x0366f818, 0x30418bb4, 0xc472}}, + {{0x06b0daa9, 0x1c71a0f6, 0x22b5d8a5, 0x3cedec78, 0x1667d885, 0x0aad6a13, 0x370e9643, 0x03806517, 0x4182}}}, + /* 3*16^51*G: */ + {{{0x22f8acb1, 0x0da54d2a, 0x13f053f4, 0x27595518, 0x2cc31eb3, 0x06de92e3, 0x1e3d685e, 0x23ce6551, 0x86f8}}, + {{0x05098a19, 0x12c10b44, 0x11652711, 0x3a98afba, 0x11b1214e, 0x325e3ed6, 0x238d6b37, 0x375a69a0, 0x2ccf}}}, + /* 5*16^51*G: */ + {{{0x3cadab66, 0x220ddedb, 0x1d35602d, 0x31a8cf0f, 0x19f9a0e1, 0x1d9a5983, 0x08e747df, 0x2f87f265, 0xa2a3}}, + {{0x0c1aeb12, 0x3d284921, 0x080ad25e, 0x0b7a294d, 0x235ee1fb, 0x01fb5d34, 0x0be67065, 0x3639ad49, 0xa93b}}}, + /* 7*16^51*G: */ + {{{0x207c25bf, 0x2274884c, 0x22d8097b, 0x3ef1ddef, 0x0080be82, 0x384919df, 0x38db9367, 0x1f3b55b9, 0x354e}}, + {{0x1a864211, 0x048e8e65, 0x1a0aa215, 0x35d5b2c1, 0x0fe5585f, 0x2f609297, 0x14070e6e, 0x18ba6ee6, 0x629d}}}, + /* 9*16^51*G: */ + {{{0x35e1dad8, 0x29f60b81, 0x2c4bd2e4, 0x2029e161, 0x099f498b, 0x173dc830, 0x2805b79b, 0x326abd77, 0xc751}}, + {{0x2e4afc8b, 0x04dacd84, 0x20a8c02d, 0x3e25c28e, 0x09a4ffe6, 0x1307f5b7, 0x19de2beb, 0x190dff1e, 0xcb98}}}, + /* 11*16^51*G: */ + {{{0x099d9ba2, 0x0c486c84, 0x3aaa757d, 0x3d95f5a5, 0x0f9ca80c, 0x2d4a1ad4, 0x1d02178a, 0x33106e74, 0xaee9}}, + {{0x3ed2ad58, 0x2358120e, 0x217490e7, 0x0b9a389a, 0x06b1f531, 0x25efec03, 0x2a36f7be, 0x3cc0b6d4, 0xb72c}}}, + /* 13*16^51*G: */ + {{{0x094d208d, 0x0ffc2092, 0x3f391a46, 0x036a3fc3, 0x1ff0cefb, 0x3d82bcac, 0x12ec56bf, 0x0fd1a9e4, 0x0d0d}}, + {{0x1d45d1b1, 0x18bd4fde, 0x31ddabfd, 0x04f03469, 0x109ff0b2, 0x1d36997e, 0x37169b04, 0x06e02b87, 0xdc37}}}, + /* 15*16^51*G: */ + {{{0x19cfd890, 0x1ba08b20, 0x0071145c, 0x0db0dcdf, 0x1441e1cb, 0x3360e1f9, 0x37535f47, 0x051ad104, 0x778d}}, + {{0x16f057f2, 0x26a1fe9f, 0x2d20acac, 0x32915223, 0x06cd3796, 0x09c6365e, 0x11af72a5, 0x2e84cec0, 0x3c85}}} + }, + { + /* 1*16^52*G: */ + {{{0x039bb85f, 0x083c270e, 0x050e62c3, 0x007ec1a8, 0x15345801, 0x160b266b, 0x2432b557, 0x0e634599, 0x55d5}}, + {{0x0fed936f, 0x1fd8c461, 0x033d9e1f, 0x035a9fc6, 0x3aa72ad9, 0x31aa7a3a, 0x38e2d059, 0x08a4127f, 0x576e}}}, + /* 3*16^52*G: */ + {{{0x12ea285a, 0x01f8ae48, 0x3b910d1c, 0x007079bd, 0x00a7a39f, 0x20163777, 0x3888b785, 0x19022053, 0x1bb4}}, + {{0x107dc702, 0x303229e6, 0x12fa94ed, 0x14a8d2e6, 0x34a4fc1e, 0x3f66e24a, 0x21125a40, 0x05afebeb, 0x8a30}}}, + /* 5*16^52*G: */ + {{{0x1539785a, 0x1404a403, 0x0297f014, 0x22341dae, 0x227a548c, 0x1cf899e1, 0x3a14ee09, 0x139c380b, 0x04bc}}, + {{0x0a62e3bb, 0x0e6411d7, 0x23275c35, 0x1c05dc9e, 0x3dfb4f87, 0x16873cfc, 0x34cc3a5f, 0x3c892e32, 0x5729}}}, + /* 7*16^52*G: */ + {{{0x2114cfb5, 0x04b52ec7, 0x3d5a6a31, 0x0d8626a8, 0x1f0876d1, 0x1ce786df, 0x08173587, 0x24bf707e, 0xd3e4}}, + {{0x297f7045, 0x33ae6a95, 0x2754eefb, 0x223c1b91, 0x15fea39c, 0x3899dafc, 0x0c48b1fe, 0x29c29cfe, 0x3604}}}, + /* 9*16^52*G: */ + {{{0x2c55ddff, 0x2899d2ee, 0x0d4b7871, 0x2b46cfd9, 0x0dc1791d, 0x3948c43f, 0x042538a4, 0x3095618a, 0xbebf}}, + {{0x3ea2f303, 0x3536c328, 0x10baa706, 0x32a08b59, 0x36576c3c, 0x284712dd, 0x204ce8a3, 0x38997025, 0x850d}}}, + /* 11*16^52*G: */ + {{{0x099ead51, 0x06bd0793, 0x1d9224e9, 0x28d50e88, 0x0784715d, 0x0a4c7458, 0x20d602fb, 0x21371cf4, 0x36e9}}, + {{0x2e0e5e3e, 0x1bee7509, 0x04280afc, 0x2aefb05c, 0x232b203b, 0x2f7f26b3, 0x3485f4bf, 0x1c51c86f, 0x1437}}}, + /* 13*16^52*G: */ + {{{0x23093df0, 0x2a2ddeec, 0x376464d7, 0x17892059, 0x1793af78, 0x1451e553, 0x204aef31, 0x1d4010fd, 0x91b6}}, + {{0x12cc9f14, 0x337a30df, 0x1caf67f5, 0x0da17e3e, 0x221c5d93, 0x31eb6a5b, 0x0a00d477, 0x36c79609, 0x07fe}}}, + /* 15*16^52*G: */ + {{{0x3b7b8dc4, 0x08d9ee1b, 0x29b3848a, 0x0d24c0a2, 0x202fac5b, 0x25f8680d, 0x0883e7c4, 0x30f1e871, 0xc5d9}}, + {{0x1b2df0ea, 0x35925e34, 0x1fd4936e, 0x363dcbf4, 0x050af3d0, 0x230e1817, 0x1b79e580, 0x2e78973f, 0x3e59}}} + }, + { + /* 1*16^53*G: */ + {{{0x32513926, 0x18b6f270, 0x3ec85ecc, 0x09a2503b, 0x3c3383cc, 0x3aeac92f, 0x0872694f, 0x21918f28, 0x8842}}, + {{0x2fb8a54d, 0x3b90a0aa, 0x3dbc15a0, 0x03ac48ba, 0x181207ce, 0x1836cd97, 0x2dd5a696, 0x10a70070, 0xf778}}}, + /* 3*16^53*G: */ + {{{0x2520f1f1, 0x34aeb065, 0x07f7da4e, 0x3c6d2799, 0x0f6f4ad7, 0x17f45a33, 0x30819d5a, 0x274dbddb, 0x3bad}}, + {{0x1698df4d, 0x2865c1c9, 0x2b672586, 0x26606893, 0x2c0e8049, 0x27e9f677, 0x0e659bcd, 0x2778cf89, 0x49f9}}}, + /* 5*16^53*G: */ + {{{0x3185ae66, 0x2c7912a2, 0x3a783df0, 0x3b05b6fb, 0x24118ba6, 0x1f7d4f44, 0x0c46d67a, 0x292c6b6c, 0xa6b3}}, + {{0x0bfbf21b, 0x2fad54fe, 0x1b248dd7, 0x2fc2977d, 0x29e8d8bc, 0x06a47365, 0x09623136, 0x3a35d8e2, 0x0cb6}}}, + /* 7*16^53*G: */ + {{{0x2c630e3a, 0x25a13393, 0x3f3f1c2a, 0x0418305f, 0x3f10c1f6, 0x1f8e9f61, 0x114a4e22, 0x23d69b24, 0x1f84}}, + {{0x06ca610a, 0x3bb67fda, 0x2359724a, 0x28e49aff, 0x1da4264b, 0x2720f46a, 0x2f963862, 0x154b3341, 0xa028}}}, + /* 9*16^53*G: */ + {{{0x041bcd10, 0x37fbcf37, 0x1b44e154, 0x2e555d91, 0x0a2eb211, 0x2899df1b, 0x1c3588b1, 0x3952fa52, 0xcfd1}}, + {{0x2a62e732, 0x30057ae6, 0x0553965a, 0x36645742, 0x052fafac, 0x1d46f56c, 0x158bb9c5, 0x07d7d802, 0xf4e3}}}, + /* 11*16^53*G: */ + {{{0x228da5fb, 0x3e987648, 0x2870e724, 0x392fd78a, 0x31291b90, 0x1e578f9d, 0x09e5512c, 0x1cc3011b, 0x4b3e}}, + {{0x3c169e48, 0x3fc298e2, 0x023472bb, 0x28e84727, 0x20b48c65, 0x32e81ee3, 0x260e9e80, 0x2593688d, 0x8c40}}}, + /* 13*16^53*G: */ + {{{0x1f894780, 0x23a46962, 0x09aec5db, 0x3a7328d6, 0x02d8f737, 0x12e2952d, 0x38fe71d5, 0x0577dd10, 0xafe9}}, + {{0x1511d444, 0x3e5a554f, 0x2c0af452, 0x27a2f9ce, 0x3f2e3690, 0x2d0d08cc, 0x04686a94, 0x30d02348, 0x3cae}}}, + /* 15*16^53*G: */ + {{{0x1182fa6e, 0x168c7f2f, 0x181c8aff, 0x298cb75a, 0x35c9e7c0, 0x1a8e8db4, 0x3ac85586, 0x120a043f, 0x0c05}}, + {{0x261cd145, 0x3af3faad, 0x376d01f6, 0x39991612, 0x1d602bf5, 0x2a2e2519, 0x1f533d1a, 0x34b2b43c, 0x2f9c}}} + }, + { + /* 1*16^54*G: */ + {{{0x14441fbb, 0x382d756b, 0x1ed115e3, 0x2aa14829, 0x3925559e, 0x183157b6, 0x221d47fb, 0x23138877, 0xb495}}, + {{0x0add7118, 0x31f8f27d, 0x14638414, 0x2e7d84cb, 0x0cb7e12d, 0x0107ef0e, 0x240efe5c, 0x39efe659, 0xfcd6}}}, + /* 3*16^54*G: */ + {{{0x371f07f1, 0x2bb5a130, 0x0d70c4a5, 0x233b6dcc, 0x06684b87, 0x3a82d918, 0x0444d232, 0x0fd79ec8, 0xb3a4}}, + {{0x201dfda5, 0x0f348bd3, 0x1cb0ecc5, 0x1e1de833, 0x175ee7ec, 0x0c89cda6, 0x3d6b8418, 0x13d6c923, 0x34c6}}}, + /* 5*16^54*G: */ + {{{0x2b559d49, 0x3df25e91, 0x1dc9b44f, 0x386d1a43, 0x0008b148, 0x18bff613, 0x3e14ac26, 0x261a691a, 0x452e}}, + {{0x1a0d6ba7, 0x11f1811b, 0x31ee4257, 0x20a15b0e, 0x21ee5259, 0x0015ed9d, 0x380d0f5c, 0x22a3c657, 0x8c5e}}}, + /* 7*16^54*G: */ + {{{0x13ce94da, 0x0de99fad, 0x2829e605, 0x2c93d095, 0x0474ee8b, 0x378370eb, 0x162bb51c, 0x3d75231b, 0x19a7}}, + {{0x3025e7bb, 0x0c111c58, 0x225eb037, 0x1894c1ab, 0x00a2e8fb, 0x29475108, 0x075c32f6, 0x12e9ea4c, 0xa250}}}, + /* 9*16^54*G: */ + {{{0x147dc697, 0x25a5b31b, 0x1e15b9bb, 0x3b862bed, 0x3c6fa417, 0x3ac2cad7, 0x334dc011, 0x16c08293, 0xbdaf}}, + {{0x06a479e2, 0x24472f9e, 0x1b7a477b, 0x048b9e21, 0x17aa0855, 0x15d791ed, 0x2836c8cf, 0x031b2f7e, 0x3cec}}}, + /* 11*16^54*G: */ + {{{0x2ce05e10, 0x2802e46d, 0x3e106202, 0x3bdf27d0, 0x0e70db8a, 0x12dffa13, 0x1d15dab8, 0x2eba57ce, 0x265d}}, + {{0x171324f4, 0x3dfc062c, 0x164c67ff, 0x18fce4cf, 0x0b5dcb06, 0x0f3a2d5b, 0x037adf3b, 0x18f4268c, 0x58df}}}, + /* 13*16^54*G: */ + {{{0x33fe5938, 0x3456f156, 0x236d7cde, 0x320c0f6d, 0x1668669e, 0x1d2754e9, 0x2639689f, 0x020fc5f9, 0xc43e}}, + {{0x183732f3, 0x19e5d5bb, 0x24407477, 0x188c1c58, 0x04402eab, 0x240c0eaf, 0x3cc58350, 0x00a48e7e, 0x54c6}}}, + /* 15*16^54*G: */ + {{{0x1dd52975, 0x0c71c3de, 0x2b44180c, 0x33c3f4c1, 0x3266ba2b, 0x314369de, 0x3848665a, 0x3c5c028f, 0x7868}}, + {{0x3c626fac, 0x005bb540, 0x29690443, 0x3dbe7b29, 0x11276c68, 0x3e871b6c, 0x17ee1113, 0x25f3cc48, 0xe890}}} + }, + { + /* 1*16^55*G: */ + {{{0x2e12e1df, 0x3093990d, 0x1761d04a, 0x29ff42df, 0x06027cd8, 0x12fc4ecd, 0x132b6413, 0x2465a23a, 0xd0e0}}, + {{0x1fd28fbe, 0x2995136e, 0x046b8df6, 0x13312f66, 0x1bf86754, 0x2d82da47, 0x11452b4e, 0x26967f9f, 0x069c}}}, + /* 3*16^55*G: */ + {{{0x084aa098, 0x2c361440, 0x16e3e02b, 0x3040502a, 0x01fa8509, 0x29f6b2ff, 0x308eb398, 0x2915284c, 0xb517}}, + {{0x0540efbf, 0x0012d67d, 0x12447fd6, 0x3522d51a, 0x326fa3a4, 0x28f8bec3, 0x3879a60e, 0x21df4307, 0x0a3d}}}, + /* 5*16^55*G: */ + {{{0x0744bfa1, 0x3656b2a9, 0x093643d6, 0x09b49f38, 0x33e387cc, 0x089c4b63, 0x166f67bc, 0x050e12d4, 0xf8ec}}, + {{0x32b65f6d, 0x1a49398c, 0x3900060c, 0x18deb170, 0x160f610a, 0x1a3ec9a7, 0x3b9a6323, 0x0d2c844f, 0x7611}}}, + /* 7*16^55*G: */ + {{{0x3227a4bb, 0x18b0efa4, 0x38d99f2f, 0x39ac7c03, 0x14f2e64b, 0x1d3ab487, 0x3fae794e, 0x3fde36de, 0x320c}}, + {{0x30f3d2d4, 0x2073241a, 0x1e2f9705, 0x11c8dd02, 0x3f629960, 0x1e5a8953, 0x28692ab7, 0x3a3501ca, 0xaf9f}}}, + /* 9*16^55*G: */ + {{{0x1c2ca683, 0x2d6d6979, 0x295a7373, 0x1b3cd782, 0x03426a20, 0x377732d5, 0x2ed8517e, 0x379f1a9e, 0x0c08}}, + {{0x3db5f259, 0x0901b6d5, 0x0ea68c69, 0x3235edf8, 0x0e0e79c3, 0x20a6737f, 0x16e19b7c, 0x1b6157a8, 0xddb7}}}, + /* 11*16^55*G: */ + {{{0x252ae5cd, 0x319eb3e0, 0x0fdd7861, 0x2d94bebd, 0x24390995, 0x1bde9133, 0x07c3d18e, 0x31dab431, 0xd1f8}}, + {{0x3e6d2dda, 0x3ae5ef0f, 0x189f4fc7, 0x2eba055a, 0x21203239, 0x265ec07d, 0x0e802ac7, 0x17719848, 0x74d4}}}, + /* 13*16^55*G: */ + {{{0x2bdc603f, 0x1e4019aa, 0x3dffe5ab, 0x1b597359, 0x3620d8c9, 0x0cfb1899, 0x090c093e, 0x20da4fce, 0xa6cb}}, + {{0x096befcc, 0x2b380f83, 0x0661735c, 0x07b05a93, 0x110b72fb, 0x366f6931, 0x3cafc8f2, 0x3239187c, 0xd823}}}, + /* 15*16^55*G: */ + {{{0x22c374b0, 0x278e984b, 0x170db4a2, 0x16cd662d, 0x024ef0bf, 0x3b25c549, 0x0332136b, 0x27247a9b, 0x8a6c}}, + {{0x378c08bd, 0x2fdf3e36, 0x00f4d583, 0x054d3d0d, 0x0132a046, 0x1e217724, 0x1ffaf79a, 0x1fd3d973, 0xe4bc}}} + }, + { + /* 1*16^56*G: */ + {{{0x2895df07, 0x29c0fc43, 0x1876bd86, 0x1d7cfe80, 0x208ffefd, 0x2c1b9c33, 0x3dfeeeb5, 0x2e1509e0, 0x68f6}}, + {{0x38712655, 0x031dbe29, 0x310bf7f9, 0x14a4f4bc, 0x245028cf, 0x201137f6, 0x00ce6fbc, 0x3faea4b9, 0xcbe1}}}, + /* 3*16^56*G: */ + {{{0x3aa89692, 0x1063e88c, 0x14c2308e, 0x0ec235be, 0x18a77671, 0x1b990490, 0x28f4de99, 0x329c6059, 0x3bdf}}, + {{0x1a510308, 0x0f6f6d0c, 0x1e2ef139, 0x370318d1, 0x1a5333c7, 0x098546bb, 0x167b8494, 0x07da1594, 0x0a72}}}, + /* 5*16^56*G: */ + {{{0x037ea1d7, 0x1e6c8d0b, 0x09aae4d0, 0x0e4d963e, 0x0d9e4fb2, 0x0a154946, 0x21056353, 0x2b256dd4, 0xaca8}}, + {{0x1ba973a2, 0x37bec412, 0x13935e9d, 0x3b6ff710, 0x072189e1, 0x01312e4a, 0x1cc20943, 0x3159f75d, 0x7f12}}}, + /* 7*16^56*G: */ + {{{0x13245b7f, 0x36c9e073, 0x0597fbf5, 0x1f59a5a4, 0x185311a3, 0x3086be63, 0x27c0e206, 0x11c136d9, 0xfa90}}, + {{0x0ddf6bef, 0x3e0cf7c5, 0x24f1d47e, 0x27bb3498, 0x31c189cb, 0x3e8fb503, 0x036a42d6, 0x230d9d2a, 0x1a1c}}}, + /* 9*16^56*G: */ + {{{0x37f0953a, 0x187de3f5, 0x315439ab, 0x124520ff, 0x3a92a818, 0x0ae3874b, 0x17d8cd67, 0x06aae47d, 0x1d43}}, + {{0x1d68f260, 0x1f1675da, 0x0707e7c1, 0x238a6a42, 0x15fae0f4, 0x0c320f38, 0x1121ebc5, 0x19f0efc6, 0x08d6}}}, + /* 11*16^56*G: */ + {{{0x25227c70, 0x28c45c4d, 0x3a3ea705, 0x0afaaccc, 0x31c60ff3, 0x12cd6cb8, 0x21137dda, 0x3a83568f, 0x6dee}}, + {{0x0369b9b7, 0x35b68e04, 0x29083dba, 0x1ebb0795, 0x2acc8428, 0x132ebfbd, 0x03e40001, 0x0fc3f1d1, 0xcbb9}}}, + /* 13*16^56*G: */ + {{{0x0421b54d, 0x2d7f57a2, 0x1564a4ff, 0x26cae0e9, 0x3a9dca57, 0x3274aec7, 0x178d8d4a, 0x170418d5, 0x2813}}, + {{0x0ee5d868, 0x3733c26e, 0x1e310d8a, 0x01253324, 0x3f8c15ef, 0x2a75d041, 0x1be1506f, 0x12af8e14, 0x9ed8}}}, + /* 15*16^56*G: */ + {{{0x28e4ac10, 0x05f95647, 0x0e24a9a9, 0x25aa04ab, 0x3fb56879, 0x0f316827, 0x1077bd6c, 0x015d882c, 0x339a}}, + {{0x0d1312a0, 0x1db6a191, 0x01cc66ef, 0x0e79e23d, 0x0f553e50, 0x1537de2b, 0x2947f438, 0x17efb75a, 0xca98}}} + }, + { + /* 1*16^57*G: */ + {{{0x27ea1f34, 0x0d36ac5d, 0x0739e0dd, 0x1af4d501, 0x3353d664, 0x10745e4e, 0x34b66c3b, 0x18288f51, 0x7f94}}, + {{0x0d9063ec, 0x22fb0b2b, 0x0e34ffc5, 0x3fe05449, 0x076661c6, 0x07cafe3c, 0x0618769f, 0x059de3ec, 0xd0d5}}}, + /* 3*16^57*G: */ + {{{0x3dfc0a9d, 0x316dd326, 0x0f77aa0d, 0x1108d6c5, 0x20a2a2de, 0x038d91ab, 0x29e022a6, 0x39fe130c, 0xdb43}}, + {{0x1e9ad713, 0x02c424ea, 0x2d2f054f, 0x0e411cd5, 0x2f9fa488, 0x15b20533, 0x2b591b8a, 0x2368af8d, 0xb016}}}, + /* 5*16^57*G: */ + {{{0x0283808d, 0x02f2c5dd, 0x1643a893, 0x23c1f38d, 0x3a78980f, 0x057a4487, 0x121aeb85, 0x0c207b83, 0xe9af}}, + {{0x39b39d33, 0x19b0be38, 0x1136d199, 0x1ae49445, 0x2f497197, 0x3c99543f, 0x3126085a, 0x32122711, 0xa976}}}, + /* 7*16^57*G: */ + {{{0x2d8426df, 0x1a4bd0b2, 0x26f8a0a2, 0x104e5693, 0x3883590f, 0x2b24e0ef, 0x06980703, 0x0cd8cb20, 0x6eb7}}, + {{0x200b4267, 0x3fdd67b8, 0x3fe1b833, 0x14ba5f20, 0x008e8d92, 0x392cb3b3, 0x07a9a030, 0x1bb045cc, 0x96c5}}}, + /* 9*16^57*G: */ + {{{0x1a16453d, 0x1f45b5f0, 0x21033dbf, 0x1fa1ef9d, 0x34d0e68b, 0x106e47e2, 0x15f45e17, 0x275781e7, 0xd397}}, + {{0x27b6d737, 0x0f2ee0c5, 0x26961a4f, 0x377d98a2, 0x32456917, 0x02495d4d, 0x1adb9a4d, 0x24cd75e6, 0xc55f}}}, + /* 11*16^57*G: */ + {{{0x2d326504, 0x3a866697, 0x3b5202cc, 0x16a6d189, 0x2efc12f6, 0x20ee2306, 0x0c2342c3, 0x24a7396e, 0x54c3}}, + {{0x3ec9e107, 0x2fc047e9, 0x08a67268, 0x294f6798, 0x14ab4447, 0x26a8a124, 0x216d0c48, 0x0c09583a, 0x4696}}}, + /* 13*16^57*G: */ + {{{0x3b5ecce7, 0x0113d5da, 0x00d21353, 0x0a0562c3, 0x1659c873, 0x3a3a0f06, 0x2d6c5b84, 0x3a6ca199, 0x3744}}, + {{0x2a247721, 0x004c8505, 0x2a6f8392, 0x3a2d7c14, 0x29ec3c28, 0x39a55bac, 0x047aa0e0, 0x383e3664, 0x9546}}}, + /* 15*16^57*G: */ + {{{0x05fef996, 0x0324a379, 0x04253515, 0x01a3d8e5, 0x33f2de14, 0x3342907b, 0x16d53324, 0x0f85f8d9, 0x1134}}, + {{0x1792aded, 0x00542b9d, 0x086f18e4, 0x33935968, 0x273765d0, 0x377e4c18, 0x28eeeb04, 0x212037ae, 0x4a9e}}} + }, + { + /* 1*16^58*G: */ + {{{0x0e6d8483, 0x3b26d35e, 0x2967f0dc, 0x3cb5ea11, 0x2ee94582, 0x23d27c6d, 0x1563d295, 0x32d828cf, 0x9c39}}, + {{0x2b2c50fb, 0x12ccd5bd, 0x1be43689, 0x2b794bcf, 0x216546bb, 0x065adef2, 0x3e51003d, 0x2fc7b924, 0xf097}}}, + /* 3*16^58*G: */ + {{{0x07a14dda, 0x1570c7e1, 0x34b4df3f, 0x1b410a59, 0x01308360, 0x1da3dc90, 0x2dad7443, 0x1eb3243a, 0x18f3}}, + {{0x25ac8364, 0x08bf370c, 0x28536cbe, 0x363df1e2, 0x1bcd0b77, 0x2fffb3b8, 0x12c26d7b, 0x12eeaa82, 0x2f94}}}, + /* 5*16^58*G: */ + {{{0x0c7d59be, 0x19d3a3a3, 0x20932fb5, 0x3a861623, 0x32736b98, 0x17ffb91d, 0x279da4ec, 0x0d630a07, 0x5413}}, + {{0x24f80590, 0x35fa87db, 0x100b3672, 0x3896c572, 0x24515a53, 0x123f4805, 0x0b024e7c, 0x3537a5a7, 0x680f}}}, + /* 7*16^58*G: */ + {{{0x076051a8, 0x3ae0327e, 0x2457ea58, 0x35dce58e, 0x385280be, 0x3f068f06, 0x194f05dc, 0x3449a46c, 0x4e2f}}, + {{0x29cc9005, 0x2bfb1d3f, 0x2c4fe2e6, 0x2e2ea964, 0x0a31bceb, 0x2cd68542, 0x0fbb2371, 0x2ef6fd7d, 0x122a}}}, + /* 9*16^58*G: */ + {{{0x16a80e09, 0x19f2a3e9, 0x225f5fe3, 0x1d7c3dd9, 0x008fa0a2, 0x13d5a04f, 0x31b59200, 0x16352fbf, 0x2de7}}, + {{0x036a1cd3, 0x358bb7d5, 0x1dad6c99, 0x06b719a5, 0x1e64a07a, 0x00cac099, 0x0ee67d7c, 0x33cc5df6, 0xdd9a}}}, + /* 11*16^58*G: */ + {{{0x3a3628ac, 0x0940d6cb, 0x35b564ec, 0x22ee8b37, 0x2e12a456, 0x1685cf1b, 0x14a5728c, 0x282b3707, 0xf597}}, + {{0x2cd3550f, 0x3a80c435, 0x012106e7, 0x0bb3e475, 0x222cc077, 0x06edca25, 0x3d4557bb, 0x05a38cca, 0x0db9}}}, + /* 13*16^58*G: */ + {{{0x2b75d6c3, 0x235a0f52, 0x13a28567, 0x0a9515f5, 0x3e40f3c4, 0x041c6086, 0x04fb908a, 0x0aa1b5bd, 0xaa22}}, + {{0x244cb028, 0x0c996939, 0x1a8c8f61, 0x1c7f252d, 0x22df4260, 0x122896bb, 0x28e76ce4, 0x21e4c006, 0x5637}}}, + /* 15*16^58*G: */ + {{{0x235790c9, 0x3ea15ce4, 0x3f3c5037, 0x006e45dc, 0x335e2e9e, 0x03190e4b, 0x315b756f, 0x2c9af365, 0x8568}}, + {{0x26b1f5ac, 0x34fd54e0, 0x385479fd, 0x11797e3e, 0x363ce801, 0x1e382b90, 0x1d2ade90, 0x09869613, 0xd3f2}}} + }, + { + /* 1*16^59*G: */ + {{{0x1c38d4e4, 0x376a5f15, 0x1b173747, 0x3f597c6c, 0x181e25e2, 0x19b9d0c0, 0x29938975, 0x21498448, 0x3d92}}, + {{0x00ccf0d3, 0x3eabbc03, 0x17abc7f6, 0x02ac4e06, 0x2869eacc, 0x015c0d70, 0x0eab53ff, 0x2829751a, 0xd32c}}}, + /* 3*16^59*G: */ + {{{0x0dd7718a, 0x01c8c960, 0x1be4e4ed, 0x3206d946, 0x36dff891, 0x05668979, 0x02fc3f7c, 0x038dcae4, 0x3b18}}, + {{0x1afd82db, 0x099898a6, 0x02d14d07, 0x1244559c, 0x05211e58, 0x12f274a4, 0x358aafaa, 0x2c45fcda, 0xf2b6}}}, + /* 5*16^59*G: */ + {{{0x13d3653d, 0x2a069446, 0x0e467d5f, 0x13b12c9d, 0x283eb213, 0x3d3d0262, 0x29c9f45e, 0x3fc0e475, 0xf352}}, + {{0x0a44f28e, 0x27999e32, 0x2c582d07, 0x06657e5c, 0x26d5055c, 0x2f5cf7f6, 0x05ebd020, 0x189b32db, 0x4472}}}, + /* 7*16^59*G: */ + {{{0x2d4478da, 0x19877c6b, 0x00e0154d, 0x173db089, 0x393ca1f1, 0x2d1736fd, 0x18c230af, 0x391c40d3, 0x670e}}, + {{0x34f563f0, 0x0a3ff93f, 0x3f247706, 0x30ee0583, 0x0750e81c, 0x19816c4e, 0x022ca254, 0x31d096e8, 0x5ca0}}}, + /* 9*16^59*G: */ + {{{0x03dbd581, 0x3138a411, 0x0d6b35ba, 0x3face20a, 0x2c6fa93c, 0x2fe8c2b3, 0x19bdbefb, 0x38d50d27, 0x96f2}}, + {{0x28f59952, 0x36693ffb, 0x04f5d454, 0x2863c754, 0x0dbaf435, 0x17638e58, 0x126cf4fe, 0x36022175, 0x09fc}}}, + /* 11*16^59*G: */ + {{{0x24e9c2fc, 0x3acd0c92, 0x3bd706a1, 0x0b3c33cb, 0x209a35e7, 0x06082c51, 0x399ac804, 0x1b945fa0, 0xc494}}, + {{0x26398ce8, 0x10d1d8dd, 0x14623123, 0x22fce3b4, 0x3b8237e4, 0x283da3d1, 0x18a4ce99, 0x00482c61, 0x7489}}}, + /* 13*16^59*G: */ + {{{0x04960b03, 0x32e45cfa, 0x0808e8f5, 0x2b0eac32, 0x094d8fb6, 0x232315e0, 0x233dbfa4, 0x2d936a6f, 0x1653}}, + {{0x30f73c69, 0x201a953a, 0x1b564e7f, 0x0e383928, 0x15a8948b, 0x2caf60fa, 0x1d5609f4, 0x1c205a79, 0xa583}}}, + /* 15*16^59*G: */ + {{{0x3b63640e, 0x155df8c6, 0x0c72df2c, 0x26edfca4, 0x05cbf497, 0x319e729a, 0x3153f500, 0x1b75fb4b, 0x5107}}, + {{0x02e4476c, 0x3da5ca1e, 0x320ef021, 0x2fa93a79, 0x20fda6c8, 0x399405cb, 0x1df76aeb, 0x09d28b5b, 0xb397}}} + }, + { + /* 1*16^60*G: */ + {{{0x244e8de3, 0x018c12c6, 0x2cc1e076, 0x02259a8b, 0x3d17915c, 0x29f73c22, 0x010b73a5, 0x266dd1a2, 0xf50b}}, + {{0x1b7f3588, 0x28fcee9b, 0x1721e854, 0x1d7c6348, 0x2dcebbe9, 0x265ce8b7, 0x18f0c878, 0x0187957c, 0xe2b5}}}, + /* 3*16^60*G: */ + {{{0x02accf8b, 0x3771adae, 0x2816fa7d, 0x34a66460, 0x39430481, 0x3cc38944, 0x05770645, 0x1fd86954, 0x598d}}, + {{0x0f6cb808, 0x2e119cf0, 0x13540b91, 0x0a26a3cd, 0x33ebcad2, 0x31458ac9, 0x32609546, 0x087dd3e3, 0x9f31}}}, + /* 5*16^60*G: */ + {{{0x24aa7b3e, 0x3ece6951, 0x16c9cea9, 0x313bc6c1, 0x1c581013, 0x34824550, 0x34c4d64f, 0x0804bd27, 0x715a}}, + {{0x3c7d081d, 0x268ce512, 0x08b47d0d, 0x06f1622a, 0x113b6242, 0x24a23e2a, 0x06c0a1f7, 0x2cec6a98, 0x5922}}}, + /* 7*16^60*G: */ + {{{0x220db220, 0x06f6da5d, 0x287ace4d, 0x0732c405, 0x387876c7, 0x273a25fe, 0x1b125c40, 0x23179aaa, 0x49ec}}, + {{0x277338c2, 0x26e2b281, 0x13b9cce9, 0x0b0c1cf9, 0x1f542984, 0x2730d219, 0x2629b3da, 0x1f53f97a, 0x99a9}}}, + /* 9*16^60*G: */ + {{{0x1e771268, 0x07af28c5, 0x10a65685, 0x13c529f6, 0x207b7a2f, 0x3c643817, 0x0b4483e6, 0x2dc35214, 0x1f8f}}, + {{0x0909c8dd, 0x2bf4c043, 0x092b3ab1, 0x074f0c47, 0x2192a14e, 0x0bb5d1c9, 0x3a2bf12c, 0x1eb6d186, 0xf53e}}}, + /* 11*16^60*G: */ + {{{0x28d9819e, 0x17b03cac, 0x02dab1a5, 0x019e4bdd, 0x38732cd6, 0x3450ae99, 0x3f61fdd5, 0x31c69925, 0xb8d5}}, + {{0x29138ac4, 0x31e2fa3a, 0x1d45c3cd, 0x3d27c4d8, 0x23dc79e2, 0x3b90d66d, 0x37f823b6, 0x13bc4c84, 0x1cd1}}}, + /* 13*16^60*G: */ + {{{0x20bca3f3, 0x2a4f6f99, 0x16004906, 0x2cd0d451, 0x00d8c4ec, 0x0fad8722, 0x2ae3ddd6, 0x2d6b196e, 0x2265}}, + {{0x117409ff, 0x160a71b1, 0x2393d5a2, 0x202984b4, 0x0964983c, 0x0c4e8ec4, 0x0fe0f61a, 0x262fd72b, 0x97a1}}}, + /* 15*16^60*G: */ + {{{0x05bac36e, 0x1cb48ffd, 0x175dcd03, 0x26265166, 0x09abcb59, 0x362a7d7f, 0x0492521f, 0x073440d6, 0xaf38}}, + {{0x31b119a9, 0x3cf621ea, 0x34d4a90f, 0x26e0bc7b, 0x1a264858, 0x15fc8a54, 0x30fbdc94, 0x021fedf7, 0x681a}}} + }, + { + /* 1*16^61*G: */ + {{{0x2037cfb4, 0x38665015, 0x3cdaa859, 0x003c91b0, 0x20b0e074, 0x1fd22036, 0x1ed0b0d7, 0x0c608ffd, 0x0425}}, + {{0x18775d23, 0x02dcc97b, 0x0ec5dd40, 0x28f93d4d, 0x261facee, 0x32934321, 0x00f7e628, 0x22f33eb8, 0xc90e}}}, + /* 3*16^61*G: */ + {{{0x06c34577, 0x213d9cd5, 0x2a52af77, 0x1027b239, 0x00e4bde6, 0x178c23a3, 0x3ca48b1f, 0x1ea838c2, 0x2755}}, + {{0x0416193c, 0x37fae6e0, 0x0c4380ba, 0x28b29cdd, 0x3d34f318, 0x235d6927, 0x05b3b77c, 0x31d61184, 0x8399}}}, + /* 5*16^61*G: */ + {{{0x2401f4d3, 0x3963f6da, 0x295b301e, 0x1b0b943a, 0x21d7decf, 0x01e0efd5, 0x073648e5, 0x1e05f496, 0x8e68}}, + {{0x0294d86b, 0x00a07a51, 0x2a191289, 0x02e5bc4b, 0x2d3cae90, 0x20268141, 0x09bfa62f, 0x2ae21b8b, 0x989c}}}, + /* 7*16^61*G: */ + {{{0x2d2aa8e6, 0x1658f789, 0x0effe2dc, 0x14d67f10, 0x27dbee20, 0x0da00f29, 0x25cf6d10, 0x05d1894f, 0x98a4}}, + {{0x206cf75b, 0x25d02fb5, 0x37ed2196, 0x0085feaa, 0x35cec9e3, 0x150bd68b, 0x063d6b11, 0x31a51f8d, 0x579a}}}, + /* 9*16^61*G: */ + {{{0x352c2d31, 0x328b323d, 0x061eecd7, 0x002aec23, 0x21a94618, 0x05b910f8, 0x140fd922, 0x151088c1, 0xe168}}, + {{0x24a50fec, 0x32e20da0, 0x09983941, 0x1d864afe, 0x2bc9343e, 0x0b990b40, 0x272142fb, 0x215724a3, 0x0700}}}, + /* 11*16^61*G: */ + {{{0x33a7cdad, 0x28ceeb8d, 0x10bcfaf4, 0x2b60f4b9, 0x0951a53c, 0x0a8b94ce, 0x113ea1ca, 0x0c52c275, 0xbfa6}}, + {{0x295cb953, 0x17e224c0, 0x04047a1c, 0x04643e32, 0x2ed1a726, 0x3e16eec7, 0x02c782a5, 0x3a065320, 0xb452}}}, + /* 13*16^61*G: */ + {{{0x0ade0fb7, 0x36f32140, 0x26518d8e, 0x1b71d37a, 0x198e200c, 0x025d79b7, 0x21cd3ecf, 0x020b42a5, 0xe687}}, + {{0x1d4d6ece, 0x05e783cc, 0x08c22599, 0x307a17be, 0x11a72117, 0x3c394c87, 0x095555e5, 0x29121a13, 0x2135}}}, + /* 15*16^61*G: */ + {{{0x0e432daf, 0x20f2d7c3, 0x2827ac9c, 0x2fb6822a, 0x074975f3, 0x30a35e54, 0x1a9e94bf, 0x1bbe18aa, 0x7ab1}}, + {{0x271bdc48, 0x045d622a, 0x34fdb013, 0x3a738eb9, 0x1ba7c5c7, 0x2460f8a3, 0x328b1a35, 0x0382a5f0, 0x584e}}} + }, + { + /* 1*16^62*G: */ + {{{0x085fbd44, 0x01d1c4a6, 0x326267ac, 0x30b2a8e7, 0x15222c89, 0x11c7385b, 0x35905e05, 0x01b6b66a, 0x9bbf}}, + {{0x3a1d3e88, 0x0d11f7e9, 0x1036ed2a, 0x352f7705, 0x2f47e8c0, 0x176bcc29, 0x120a3675, 0x1fea1378, 0x1bcc}}}, + /* 3*16^62*G: */ + {{{0x34a7b506, 0x2deb9e4a, 0x3860be08, 0x1d62eeb9, 0x100ee922, 0x33ecab9d, 0x35bd3429, 0x3dfd96ce, 0x646f}}, + {{0x2b36f946, 0x25e70494, 0x08e6995c, 0x0b7f13f0, 0x0a8fe849, 0x078cc601, 0x218a55a6, 0x0aa74192, 0xbc11}}}, + /* 5*16^62*G: */ + {{{0x0103b553, 0x152dc727, 0x3385a801, 0x183a89e0, 0x3e507ebe, 0x304002c9, 0x3d39a9d0, 0x151ea985, 0x7cc0}}, + {{0x0d45a526, 0x1e672e8f, 0x0228b7d5, 0x061682ab, 0x3c94c400, 0x1ca32ce7, 0x0045abdd, 0x27af48ca, 0x7b32}}}, + /* 7*16^62*G: */ + {{{0x19e717a4, 0x30bbd150, 0x0f01b81a, 0x368af6ab, 0x2ee15468, 0x0fb54db6, 0x1db4e056, 0x146642f0, 0x9468}}, + {{0x3526dea3, 0x1d7c3f46, 0x30acd9ca, 0x2665643d, 0x267dc057, 0x23439ac9, 0x191a8b3b, 0x1e108371, 0xca5c}}}, + /* 9*16^62*G: */ + {{{0x08362735, 0x3e0b0dbc, 0x12b327bd, 0x3e2cdfbc, 0x12d1f5df, 0x163e3a91, 0x0e8fab12, 0x23c6f9f8, 0xe1b9}}, + {{0x0ecb11b7, 0x2584e327, 0x374090af, 0x067b8cf7, 0x3b2ba27e, 0x16d26a0e, 0x36a0b7e0, 0x3a6b66a5, 0xca83}}}, + /* 11*16^62*G: */ + {{{0x39046346, 0x2d02ef60, 0x01440083, 0x296379cc, 0x27962d56, 0x2281af65, 0x207ef6d0, 0x3c9723f5, 0x3536}}, + {{0x0c14fea6, 0x100418af, 0x2d9b3e29, 0x1b0f47a8, 0x29e1c39e, 0x285a8694, 0x3509e73b, 0x07f85f78, 0x1e27}}}, + /* 13*16^62*G: */ + {{{0x2847f6f8, 0x3ffe0fb5, 0x140ef530, 0x0a6d47ef, 0x3f8c3c10, 0x0547cd2d, 0x3d4de690, 0x0091af88, 0x0df5}}, + {{0x3b1633a6, 0x1332a29a, 0x1df3449b, 0x1b8599a2, 0x2174ab4c, 0x0cb13ef0, 0x2f1ca2b2, 0x011fca76, 0x2107}}}, + /* 15*16^62*G: */ + {{{0x3d4f1b81, 0x2173abb7, 0x0f4bb151, 0x1a69e923, 0x129330ad, 0x378eccd9, 0x13398f69, 0x3575133d, 0xca9d}}, + {{0x02b7c8bd, 0x3318b2b9, 0x2ada10f8, 0x325d82fe, 0x067b3e66, 0x11c7ed11, 0x22c56402, 0x2621946f, 0x6e4b}}} + }, + { + /* 1*16^63*G: */ + {{{0x044c0448, 0x3ab4c8cd, 0x10319e31, 0x0d5da1b0, 0x3893e796, 0x0ff32ced, 0x3dfa5494, 0x2b7d4a50, 0xb12f}}, + {{0x3369de57, 0x195d79da, 0x2fc4df29, 0x0179c0cc, 0x32a6a71d, 0x3e3d99de, 0x0f4ace96, 0x1165666c, 0x02e2}}}, + /* 3*16^63*G: */ + {{{0x24e9151f, 0x14db1151, 0x00d8418f, 0x3a8ce672, 0x18fb3e67, 0x15776a47, 0x10568432, 0x238d3c71, 0x4838}}, + {{0x0d7a9434, 0x2fb927b7, 0x3de83101, 0x2c504454, 0x082bcc99, 0x14ce4c55, 0x04e9e6a2, 0x18eafd39, 0xb0ec}}}, + /* 5*16^63*G: */ + {{{0x0e5b833d, 0x1f7ed296, 0x20b2419d, 0x0e801cf2, 0x0109c959, 0x177e0414, 0x053da5e6, 0x1911eb85, 0xde8e}}, + {{0x214c5cc7, 0x03f3066a, 0x101c6c9f, 0x1f80c4ca, 0x2de26598, 0x08a232f5, 0x113d8e33, 0x118f0542, 0x05e1}}}, + /* 7*16^63*G: */ + {{{0x01f7df48, 0x38964fab, 0x071317b3, 0x19d1cfae, 0x18f385b2, 0x156d3939, 0x07e9e8e5, 0x04b4293b, 0xb18b}}, + {{0x2846b546, 0x06cf5643, 0x3d1e5599, 0x20fdf920, 0x2cc33b3c, 0x3109af16, 0x1fb445ce, 0x0648a8d6, 0xff53}}}, + /* 9*16^63*G: */ + {{{0x19c9fd24, 0x094eb71a, 0x1211e0df, 0x33762611, 0x28694402, 0x072a931c, 0x09433c7c, 0x2b5c7237, 0x5f51}}, + {{0x2d2ffd3a, 0x30eeba21, 0x224a9969, 0x087d8911, 0x2e4d0387, 0x0c17ef30, 0x2714a0cd, 0x3bc477df, 0x2bbb}}}, + /* 11*16^63*G: */ + {{{0x17cec42e, 0x0f1018ff, 0x2e3bdb7e, 0x0f724cfb, 0x06d8556f, 0x208bb90d, 0x01ebbfa5, 0x10364dcc, 0xfdf3}}, + {{0x0db6908b, 0x23d8d2df, 0x0de30c83, 0x1b9aafd4, 0x0ad2c445, 0x307f9ce3, 0x0c6e1d70, 0x2698e5a3, 0xa3e5}}}, + /* 13*16^63*G: */ + {{{0x21dc4fe8, 0x30625153, 0x2072415f, 0x3a284ea5, 0x3dc983f9, 0x114a45ed, 0x25d79ec6, 0x3af22e7a, 0xe3ca}}, + {{0x1307b403, 0x1ad82dc8, 0x14f86a11, 0x0c00d968, 0x01f97651, 0x00d72e2c, 0x05928d22, 0x24f49efc, 0x97f0}}}, + /* 15*16^63*G: */ + {{{0x3c119eff, 0x10535974, 0x29f9b846, 0x240b8302, 0x0fa00339, 0x10697396, 0x065b89af, 0x0b6e50aa, 0x0331}}, + {{0x38b1b950, 0x3a568ea7, 0x3515585f, 0x3b1676d7, 0x09e86f0a, 0x3ba8c5e0, 0x324df104, 0x36991acd, 0x6e3e}}} + }, diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/options.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/options.h new file mode 100644 index 0000000..e673c67 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/options.h @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __OPTIONS_H__ +#define __OPTIONS_H__ + +// use precomputed Curve Points (some scalar multiples of curve base point G) +#ifndef USE_PRECOMPUTED_CP +#define USE_PRECOMPUTED_CP 1 +#endif + +// use fast inverse method +#ifndef USE_INVERSE_FAST +#define USE_INVERSE_FAST 1 +#endif + +// support for printing bignum256 structures via printf +#ifndef USE_BN_PRINT +#define USE_BN_PRINT 0 +#endif + +// use deterministic signatures +#ifndef USE_RFC6979 +#define USE_RFC6979 1 +#endif + +// implement BIP32 caching +//#ifndef USE_BIP32_CACHE +//#define USE_BIP32_CACHE 1 +//#define BIP32_CACHE_SIZE 10 +//#define BIP32_CACHE_MAXDEPTH 8 +//#endif + +// support constructing BIP32 nodes from ed25519 and curve25519 curves. +//#ifndef USE_BIP32_25519_CURVES +//#define USE_BIP32_25519_CURVES 1 +//#endif + +// implement BIP39 caching +//#ifndef USE_BIP39_CACHE +//#define USE_BIP39_CACHE 1 +//#define BIP39_CACHE_SIZE 4 +//#endif + +// support Ethereum operations +#ifndef USE_ETHEREUM +#define USE_ETHEREUM 1 +#endif + +// support Graphene operations (STEEM, BitShares) +//#ifndef USE_GRAPHENE +//#define USE_GRAPHENE 0 +//#endif + +// support NEM operations +#ifndef USE_NEM +#define USE_NEM 0 +#endif + +// support MONERO operations +#ifndef USE_MONERO +#define USE_MONERO 0 +#endif + +// support CARDANO operations +#ifndef USE_CARDANO +#define USE_CARDANO 0 +#endif + +// support Keccak hashing +#ifndef USE_KECCAK +#define USE_KECCAK 1 +#endif + +// add way how to mark confidential data +#ifndef CONFIDENTIAL +#define CONFIDENTIAL +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.c new file mode 100644 index 0000000..2d27b01 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.c @@ -0,0 +1,407 @@ +/** +* Web3E uses Tiny Mersenne Twister only 127 bit internal state +* +* @author Mutsuo Saito (Hiroshima University) +* @author Makoto Matsumoto (University of Tokyo) +* +* Adapted from here: https://github.com/MersenneTwister-Lab/TinyMT.git +* +* Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, +* Hiroshima University and The University of Tokyo. +* All rights reserved. +* +* The 3-clause BSD License is applied to this software, see +* LICENSE.txt +*/ + +#include "rand.h" +#include +#include + +#define TINYMT32_MEXP 127 +#define TINYMT32_SH0 1 +#define TINYMT32_SH1 10 +#define TINYMT32_SH8 8 +#define TINYMT32_MASK UINT32_C(0x7fffffff) +#define TINYMT32_MUL (1.0f / 16777216.0f) + +extern unsigned long millis(); +extern unsigned long micros(); + + +/** +* tinymt32 internal state vector and parameters +*/ +struct TINYMT32_T { + uint32_t status[4]; + uint32_t mat1; + uint32_t mat2; + uint32_t tmat; +}; + +typedef struct TINYMT32_T tinymt32_t; + +void tinymt32_init(tinymt32_t * random, uint32_t seed); +void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[], + int key_length); + +#if defined(__GNUC__) +/** +* This function always returns 127 +* @param random not used +* @return always 127 +*/ +inline static int tinymt32_get_mexp( + tinymt32_t * random __attribute__((unused))) { + return TINYMT32_MEXP; + } +#else +inline static int tinymt32_get_mexp(tinymt32_t * random) { + return TINYMT32_MEXP; +} +#endif + +/** +* This function changes internal state of tinymt32. +* Users should not call this function directly. +* @param random tinymt internal status +*/ +inline static void tinymt32_next_state(tinymt32_t * random) { + uint32_t x; + uint32_t y; + + y = random->status[3]; + x = (random->status[0] & TINYMT32_MASK) + ^ random->status[1] + ^ random->status[2]; + x ^= (x << TINYMT32_SH0); + y ^= (y >> TINYMT32_SH0) ^ x; + random->status[0] = random->status[1]; + random->status[1] = random->status[2]; + random->status[2] = x ^ (y << TINYMT32_SH1); + random->status[3] = y; + random->status[1] ^= -((int32_t)(y & 1)) & random->mat1; + random->status[2] ^= -((int32_t)(y & 1)) & random->mat2; +} + +/** +* This function outputs 32-bit unsigned integer from internal state. +* Users should not call this function directly. +* @param random tinymt internal status +* @return 32-bit unsigned pseudorandom number +*/ +inline static uint32_t tinymt32_temper(tinymt32_t * random) { + uint32_t t0, t1; + t0 = random->status[3]; + t1 = random->status[0] + + (random->status[2] >> TINYMT32_SH8); + t0 ^= t1; + t0 ^= -((int32_t)(t1 & 1)) & random->tmat; + return t0; +} + +/** +* This function outputs floating point number from internal state. +* Users should not call this function directly. +* @param random tinymt internal status +* @return floating point number r (1.0 <= r < 2.0) +*/ +inline static float tinymt32_temper_conv(tinymt32_t * random) { + uint32_t t0, t1; + union { + uint32_t u; + float f; + } conv; + + t0 = random->status[3]; + t1 = random->status[0] + + (random->status[2] >> TINYMT32_SH8); + t0 ^= t1; + conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9) + | UINT32_C(0x3f800000); + return conv.f; +} + +/** +* This function outputs floating point number from internal state. +* Users should not call this function directly. +* @param random tinymt internal status +* @return floating point number r (1.0 < r < 2.0) +*/ +inline static float tinymt32_temper_conv_open(tinymt32_t * random) { + uint32_t t0, t1; + union { + uint32_t u; + float f; + } conv; + + t0 = random->status[3]; + t1 = random->status[0] + + (random->status[2] >> TINYMT32_SH8); + t0 ^= t1; + conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9) + | UINT32_C(0x3f800001); + return conv.f; +} + +/** +* This function outputs 32-bit unsigned integer from internal state. +* @param random tinymt internal status +* @return 32-bit unsigned integer r (0 <= r < 2^32) +*/ +inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper(random); +} + +/** +* This function outputs floating point number from internal state. +* This function is implemented using multiplying by (1 / 2^24). +* floating point multiplication is faster than using union trick in +* my Intel CPU. +* @param random tinymt internal status +* @return floating point number r (0.0 <= r < 1.0) +*/ +inline static float tinymt32_generate_float(tinymt32_t * random) { + tinymt32_next_state(random); + return (tinymt32_temper(random) >> 8) * TINYMT32_MUL; +} + +/** +* This function outputs floating point number from internal state. +* This function is implemented using union trick. +* @param random tinymt internal status +* @return floating point number r (1.0 <= r < 2.0) +*/ +inline static float tinymt32_generate_float12(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper_conv(random); +} + +/** +* This function outputs floating point number from internal state. +* This function is implemented using union trick. +* @param random tinymt internal status +* @return floating point number r (0.0 <= r < 1.0) +*/ +inline static float tinymt32_generate_float01(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper_conv(random) - 1.0f; +} + +/** +* This function outputs floating point number from internal state. +* This function may return 1.0 and never returns 0.0. +* @param random tinymt internal status +* @return floating point number r (0.0 < r <= 1.0) +*/ +inline static float tinymt32_generate_floatOC(tinymt32_t * random) { + tinymt32_next_state(random); + return 1.0f - tinymt32_generate_float(random); +} + +/** +* This function outputs floating point number from internal state. +* This function returns neither 0.0 nor 1.0. +* @param random tinymt internal status +* @return floating point number r (0.0 < r < 1.0) +*/ +inline static float tinymt32_generate_floatOO(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper_conv_open(random) - 1.0f; +} + +/** +* This function outputs double precision floating point number from +* internal state. The returned value has 32-bit precision. +* In other words, this function makes one double precision floating point +* number from one 32-bit unsigned integer. +* @param random tinymt internal status +* @return floating point number r (0.0 <= r < 1.0) +*/ +inline static double tinymt32_generate_32double(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper(random) * (1.0 / 4294967296.0); +} + +#define MIN_LOOP 8 +#define PRE_LOOP 8 + +static tinymt32_t tinymt; + +/** +* This function represents a function used in the initialization +* by init_by_array +* @param x 32-bit integer +* @return 32-bit integer +*/ +static uint32_t ini_func1(uint32_t x) { + return (x ^ (x >> 27)) * UINT32_C(1664525); +} + +/** +* This function represents a function used in the initialization +* by init_by_array +* @param x 32-bit integer +* @return 32-bit integer +*/ +static uint32_t ini_func2(uint32_t x) { + return (x ^ (x >> 27)) * UINT32_C(1566083941); +} + +/** +* This function certificate the period of 2^127-1. +* @param random tinymt state vector. +*/ +static void period_certification(tinymt32_t * random) { + if ((random->status[0] & TINYMT32_MASK) == 0 && + random->status[1] == 0 && + random->status[2] == 0 && + random->status[3] == 0) { + random->status[0] = 'T'; + random->status[1] = 'I'; + random->status[2] = 'N'; + random->status[3] = 'Y'; + } +} + +/** +* This function initializes the internal state array with a 32-bit +* unsigned integer seed. +* @param random tinymt state vector. +* @param seed a 32-bit unsigned integer used as a seed. +*/ +void tinymt32_init(tinymt32_t * random, uint32_t seed) { + random->status[0] = seed; + random->status[1] = random->mat1; + random->status[2] = random->mat2; + random->status[3] = random->tmat; + for (int i = 1; i < MIN_LOOP; i++) { + random->status[i & 3] ^= i + UINT32_C(1812433253) + * (random->status[(i - 1) & 3] + ^ (random->status[(i - 1) & 3] >> 30)); + } + period_certification(random); + for (int i = 0; i < PRE_LOOP; i++) { + tinymt32_next_state(random); + } +} + +/** +* This function initializes the internal state array, +* with an array of 32-bit unsigned integers used as seeds +* @param random tinymt state vector. +* @param init_key the array of 32-bit integers, used as a seed. +* @param key_length the length of init_key. +*/ +void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[], + int key_length) { + const int lag = 1; + const int mid = 1; + const int size = 4; + int i, j; + int count; + uint32_t r; + uint32_t * st = &random->status[0]; + + st[0] = 0; + st[1] = random->mat1; + st[2] = random->mat2; + st[3] = random->tmat; + if (key_length + 1 > MIN_LOOP) { + count = key_length + 1; + } + else { + count = MIN_LOOP; + } + r = ini_func1(st[0] ^ st[mid % size] + ^ st[(size - 1) % size]); + st[mid % size] += r; + r += key_length; + st[(mid + lag) % size] += r; + st[0] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(st[i % size] + ^ st[(i + mid) % size] + ^ st[(i + size - 1) % size]); + st[(i + mid) % size] += r; + r += init_key[j] + i; + st[(i + mid + lag) % size] += r; + st[i % size] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(st[i % size] + ^ st[(i + mid) % size] + ^ st[(i + size - 1) % size]); + st[(i + mid) % size] += r; + r += i; + st[(i + mid + lag) % size] += r; + st[i % size] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(st[i % size] + + st[(i + mid) % size] + + st[(i + size - 1) % size]); + st[(i + mid) % size] ^= r; + r -= i; + st[(i + mid + lag) % size] ^= r; + st[i % size] = r; + i = (i + 1) % size; + } + period_certification(random); + for (i = 0; i < PRE_LOOP; i++) { + tinymt32_next_state(random); + } +} + +uint32_t random32(void) +{ + static int initialized = 0; + if (!initialized) { + tinymt32_init(&tinymt, (uint32_t)micros()); + initialized = 1; + } + return tinymt32_generate_uint32(&tinymt); +} + +void randomInitFromBuffer(uint32_t *buffer, int elements) +{ + tinymt32_init_by_array(&tinymt, buffer, elements); +} + +uint32_t random32v(uint32_t randm) +{ + tinymt32_init(&tinymt, ((uint32_t)micros()) * ((uint32_t)micros() + randm)); //ensure passing 0 as randm doesn't result in predictable init + return tinymt32_generate_uint32(&tinymt); +} + +void random_buffer(uint8_t *buf, size_t len) +{ + uint32_t r = 0; + for (size_t i = 0; i < len; i++) { + if (i % 4 == 0) { + r = random32(); + } + buf[i] = (r >> ((i % 4) * 8)) & 0xFF; + } +} + +uint32_t random_uniform(uint32_t n) +{ + uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n); + while ((x = random32()) >= max); + return x / (max / n); +} + +void random_permute(char *str, size_t len) +{ + for (int i = len - 1; i >= 1; i--) { + int j = random_uniform(i + 1); + char t = str[j]; + str[j] = str[i]; + str[i] = t; + } +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.h new file mode 100644 index 0000000..68a863d --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rand.h @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __RAND_H__ +#define __RAND_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t random32v(uint32_t randm); +uint32_t random32(void); +void random_buffer(uint8_t *buf, size_t len); +void randomInitFromBuffer(uint32_t *buffer, int elements); + +uint32_t random_uniform(uint32_t n); +void random_permute(char *buf, size_t len); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.c new file mode 100644 index 0000000..ec808a7 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.c @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * Copyright (c) 2015 Jochen Hoenicke + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "rfc6979.h" +#include "hmac.h" +#include "memzero.h" + +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { + uint8_t bx[2*32]; + uint8_t buf[32 + 1 + 2*32]; + + memcpy(bx, priv_key, 32); + memcpy(bx+32, hash, 32); + + memset(state->v, 1, sizeof(state->v)); + memset(state->k, 0, sizeof(state->k)); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x01; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + + memzero(bx, sizeof(bx)); + memzero(buf, sizeof(buf)); +} + +// generate next number from deterministic random number generator +void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) +{ + uint8_t buf[32 + 1]; + + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + memcpy(rnd, buf, 32); + memzero(buf, sizeof(buf)); +} + +// generate K in a deterministic way, according to RFC6979 +// http://tools.ietf.org/html/rfc6979 +void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) +{ + uint8_t buf[32]; + generate_rfc6979(buf, state); + bn_read_be(buf, k); + memzero(buf, sizeof(buf)); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.h new file mode 100644 index 0000000..e541d6a --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/rfc6979.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * Copyright (c) 2015-2017 Jochen Hoenicke + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __RFC6979_H__ +#define __RFC6979_H__ + +#include +#include "bignum.h" + +// rfc6979 pseudo random number generator state +typedef struct { + uint8_t v[32], k[32]; +} rfc6979_state; + +void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng); +void generate_rfc6979(uint8_t rnd[32], rfc6979_state *rng); +void generate_k_rfc6979(bignum256 *k, rfc6979_state *rng); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.c new file mode 100644 index 0000000..66b13ca --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.c @@ -0,0 +1,343 @@ +/* + * RIPE MD-160 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include + +#include "ripemd160.h" +#include "memzero.h" + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (uint8_t) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (uint8_t) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (uint8_t) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (uint8_t) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * RIPEMD-160 context setup + */ +void ripemd160_Init(RIPEMD160_CTX *ctx) +{ + memset(ctx, 0, sizeof(RIPEMD160_CTX)); + ctx->total[0] = 0; + ctx->total[1] = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +void ripemd160_process( RIPEMD160_CTX *ctx, const uint8_t data[RIPEMD160_BLOCK_LENGTH] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( x ^ y ^ z ) +#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) +#define F3( x, y, z ) ( ( x | ~y ) ^ z ) +#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) +#define F5( x, y, z ) ( x ^ ( y | ~z ) ) + +#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + a += f( b, c, d ) + X[r] + k; \ + a = S( a, s ) + e; \ + c = S( c, 10 ); + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + P( a, b, c, d, e, r, s, F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; +} +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +void ripemd160_Update( RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen ) +{ + uint32_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = RIPEMD160_BLOCK_LENGTH - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + ripemd160_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= RIPEMD160_BLOCK_LENGTH ) + { + ripemd160_process( ctx, input ); + input += RIPEMD160_BLOCK_LENGTH; + ilen -= RIPEMD160_BLOCK_LENGTH; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const uint8_t ripemd160_padding[RIPEMD160_BLOCK_LENGTH] = +{ + 0x80, 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, 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 +}; + +/* + * RIPEMD-160 final digest + */ +void ripemd160_Final( RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH] ) +{ + uint32_t last, padn; + uint32_t high, low; + uint8_t msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ripemd160_Update( ctx, ripemd160_padding, padn ); + ripemd160_Update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + memzero(ctx, sizeof(RIPEMD160_CTX)); +} + +/* + * output = RIPEMD-160( input buffer ) + */ +void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]) +{ + RIPEMD160_CTX ctx; + ripemd160_Init( &ctx ); + ripemd160_Update( &ctx, msg, msg_len ); + ripemd160_Final( &ctx, hash ); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.h new file mode 100644 index 0000000..a62de5c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/ripemd160.h @@ -0,0 +1,20 @@ +#ifndef __RIPEMD160_H__ +#define __RIPEMD160_H__ + +#include + +#define RIPEMD160_BLOCK_LENGTH 64 +#define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct _RIPEMD160_CTX { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */ +} RIPEMD160_CTX; + +void ripemd160_Init(RIPEMD160_CTX *ctx); +void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen); +void ripemd160_Final(RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH]); +void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.c new file mode 100644 index 0000000..0159f3f --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.c @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "secp256k1.h" + +const ecdsa_curve secp256k1 = { + /* .prime */ { + /*.val =*/ {0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} + }, + + /* G */ { + /*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}}, + /*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}} + }, + + /* order */ { + /*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff} + }, + + /* order_half */ { + /*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff} + }, + + /* a */ 0, + + /* b */ { + /*.val =*/{7} + } + +#if USE_PRECOMPUTED_CP + , + /* cp */ { +#include "secp256k1.table" + } +#endif +}; + +const curve_info secp256k1_info = { + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, +}; + +const curve_info secp256k1_smart_info = { + .bip32_name = "Bitcoin seed", + .params = &secp256k1, + .hasher_base58 = HASHER_SHA3K, + .hasher_sign = HASHER_SHA2, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, +}; diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.h new file mode 100644 index 0000000..234ca97 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2013-2014 Tomas Dzetkulic + * Copyright (c) 2013-2014 Pavol Rusnak + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SECP256K1_H__ +#define __SECP256K1_H__ + +#include + +#include "ecdsa.h" +#include "bip32.h" + +extern const ecdsa_curve secp256k1; +extern const curve_info secp256k1_info; +extern const curve_info secp256k1_decred_info; +extern const curve_info secp256k1_groestl_info; +extern const curve_info secp256k1_smart_info; + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.table b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.table new file mode 100644 index 0000000..9fd3c72 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/secp256k1.table @@ -0,0 +1,1664 @@ + { + /* 1*16^0*G: */ + {{{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x070b0702, 0x018a573a, 0x0bbac55a, 0x199fbe77, 0x79be}}, + {{0x3b10d4b8, 0x311f423f, 0x28554199, 0x05ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}}}, + /* 3*16^0*G: */ + {{{0x3ce036f9, 0x1807c44e, 0x36f99b08, 0x0c721160, 0x1d5229b5, 0x113e17e2, 0x0c310493, 0x22806496, 0xf930}}, + {{0x04b8e672, 0x32e7f5d6, 0x0c2231b6, 0x002a664d, 0x37f35665, 0x0cdf98a8, 0x1e8140fe, 0x1ec3d8cb, 0x388f}}}, + /* 5*16^0*G: */ + {{{0x3240efe4, 0x2ea355a6, 0x0619ab7c, 0x22e12f77, 0x1c5128e8, 0x129c9429, 0x3209355b, 0x37934681, 0x2f8b}}, + {{0x26ac62d6, 0x32a1f4ea, 0x30d6840d, 0x2209c6ea, 0x09c426f7, 0x2ea7769b, 0x1e3d6d4d, 0x08898db9, 0xd8ac}}}, + /* 7*16^0*G: */ + {{{0x0ac4f9bc, 0x24af77b7, 0x330e39ce, 0x1066df80, 0x2a7a0e3d, 0x23cd97cb, 0x1b4eaa39, 0x3c191b97, 0x5cbd}}, + {{0x087264da, 0x142098a0, 0x3fde7b5a, 0x04f42e04, 0x1a54dba8, 0x1e35b618, 0x15960a31, 0x32902e89, 0x6aeb}}}, + /* 9*16^0*G: */ + {{{0x3c27ccbe, 0x0d7c4437, 0x057e714c, 0x25e5a5d3, 0x159abde0, 0x345e2a7d, 0x3f65309a, 0x2138bc31, 0xacd4}}, + {{0x064f9c37, 0x173098ab, 0x35f8e0f0, 0x3622290d, 0x3b61e9ad, 0x2025c5d8, 0x3d9fd643, 0x22486c29, 0xcc33}}}, + /* 11*16^0*G: */ + {{{0x1da008cb, 0x2fb05e25, 0x1c17891b, 0x126602f9, 0x065aac56, 0x1091adc3, 0x1411e5ef, 0x39fe162a, 0x774a}}, + {{0x0953c61b, 0x0075d327, 0x3f9d6a83, 0x0b6c78b7, 0x37b36537, 0x0f755b5e, 0x35e19024, 0x280cbada, 0xd984}}}, + /* 13*16^0*G: */ + {{{0x19405aa8, 0x3bb77e3c, 0x10e58cdd, 0x1d7ef198, 0x348651b0, 0x0748170d, 0x1288bc7d, 0x1cf0b65d, 0xf287}}, + {{0x1b03ed81, 0x26d72d4b, 0x21fa91f2, 0x0681b694, 0x0daf473a, 0x084bad97, 0x00a89758, 0x240ba362, 0x0ab0}}}, + /* 15*16^0*G: */ + {{{0x227e080e, 0x12b6f3e3, 0x085f79e4, 0x39651bcf, 0x1ff41131, 0x196b8c25, 0x3ea965a4, 0x1353df50, 0xd792}}, + {{0x36a26b58, 0x1413727f, 0x096d3a5c, 0x102bcaf6, 0x0c6defea, 0x10bb08a3, 0x072a6838, 0x0a1caa1b, 0x581e}}} + }, + { + /* 1*16^1*G: */ + {{{0x2a6dec0a, 0x113ba278, 0x07a5ae9c, 0x28c4da6e, 0x023e97b2, 0x06aaf087, 0x29ec5301, 0x33a4ed67, 0xe60f}}, + {{0x29616821, 0x07ccb339, 0x0d23f0be, 0x25a24791, 0x39371012, 0x267cd3d5, 0x195929db, 0x141ce679, 0xf7e3}}}, + /* 3*16^1*G: */ + {{{0x1118e5c3, 0x2f61c2a8, 0x12bebc19, 0x15e6c9d1, 0x265b4bfc, 0x0595bbd3, 0x1307db44, 0x0cd76591, 0x6eca}}, + {{0x05a08668, 0x2628bde0, 0x3f8ec344, 0x125a8e8e, 0x3875a03a, 0x3d5e41d2, 0x20710592, 0x08ed5e9e, 0xd501}}}, + /* 5*16^1*G: */ + {{{0x0f87f62e, 0x3b34c785, 0x37161270, 0x39b98e18, 0x0659f010, 0x31d13b4d, 0x390ec0d7, 0x0eefbc6f, 0xe962}}, + {{0x244ee737, 0x0c04fabe, 0x168844e5, 0x1810f277, 0x1aa929fe, 0x3a54ea3b, 0x299e9e0f, 0x1d0ed2f0, 0x38a9}}}, + /* 7*16^1*G: */ + {{{0x2a8d733c, 0x2c2ab7e0, 0x2fca8f9e, 0x309d2fd8, 0x00d682ff, 0x128dbc82, 0x21dba088, 0x375cf945, 0xbc82}}, + {{0x347797f0, 0x39e18413, 0x33897301, 0x24e82eb9, 0x1f02dfae, 0x26d2fdc6, 0x31cac54a, 0x230e8112, 0xe5f2}}}, + /* 9*16^1*G: */ + {{{0x1fbc7671, 0x1fbf88c5, 0x2858e32d, 0x0fc6f214, 0x18f49074, 0x0a47385e, 0x17211d20, 0x049231d9, 0x8e3d}}, + {{0x18717dec, 0x3bc77190, 0x23e144a7, 0x0d4aeaa9, 0x13e90eb9, 0x1203864e, 0x3cb81f64, 0x123843b3, 0x099a}}}, + /* 11*16^1*G: */ + {{{0x3eb31db2, 0x0ca1d0ca, 0x0f506a0f, 0x32ba09e2, 0x08a2b68f, 0x2864fb42, 0x0a498896, 0x246a888d, 0x78a8}}, + {{0x39fa4343, 0x01a7588e, 0x000b82d3, 0x0de6f376, 0x302df654, 0x17c9549c, 0x035cbfcf, 0x28d6fad4, 0x6912}}}, + /* 13*16^1*G: */ + {{{0x0db0e595, 0x14d23dde, 0x3a082bb6, 0x058f2e7e, 0x2076eba7, 0x38dd9605, 0x31b17d7c, 0x1e061576, 0x7d86}}, + {{0x3c733de8, 0x265478ea, 0x225d5329, 0x0de11383, 0x0f883829, 0x18b8afb5, 0x2f8772e5, 0x26b7fb21, 0xe2b9}}}, + /* 15*16^1*G: */ + {{{0x16060dfc, 0x023fbe14, 0x05e6a2a0, 0x1517e108, 0x1ab08676, 0x252e7710, 0x02ac8484, 0x0c43c016, 0xddc5}}, + {{0x27820ca8, 0x2d7e2adb, 0x3d04730f, 0x36ebf1aa, 0x0f0e9041, 0x06adb732, 0x19692019, 0x0bcebc83, 0xba0d}}} + }, + { + /* 1*16^2*G: */ + {{{0x15f51508, 0x191b88ff, 0x1ac1ca10, 0x30e72af5, 0x2de238d8, 0x29b8f85c, 0x209d9ea2, 0x098c84b1, 0x8282}}, + {{0x36e26caf, 0x0c6dbabf, 0x37b17bed, 0x3584eb0b, 0x360ace62, 0x095ba0c2, 0x3dfe45e8, 0x2a026155, 0x11f8}}}, + /* 3*16^2*G: */ + {{{0x257e8dfa, 0x33f032e7, 0x3c7e184f, 0x20246468, 0x298ca009, 0x28c3e2b2, 0x19c4c0d9, 0x33cbfc1e, 0x8262}}, + {{0x3bac376a, 0x173fe363, 0x314c4783, 0x2dbb4cca, 0x334f3457, 0x3b88bb16, 0x09e4e66f, 0x25788244, 0x83fd}}}, + /* 5*16^2*G: */ + {{{0x026bdb6f, 0x014b922c, 0x3734b949, 0x2906f51e, 0x299c877c, 0x0416c933, 0x0ddd5168, 0x1722c768, 0x1982}}, + {{0x049cfc9b, 0x177dc213, 0x0f6d3a6b, 0x3a7bb323, 0x359f6ceb, 0x09873253, 0x0878f320, 0x0c43c353, 0x6294}}}, + /* 7*16^2*G: */ + {{{0x3d82824c, 0x03b42548, 0x21534e65, 0x29638d17, 0x02999edf, 0x17d5bb1b, 0x0191443c, 0x361b0458, 0x6f12}}, + {{0x06eb34d0, 0x15e70d20, 0x054bc5b8, 0x07249042, 0x22376939, 0x2653cff5, 0x3bfa0875, 0x3dfd12ac, 0x5c4f}}}, + /* 9*16^2*G: */ + {{{0x1b453629, 0x1db7700b, 0x359e6030, 0x33f73703, 0x3abef645, 0x189c5a88, 0x2aa5d142, 0x231be682, 0x203a}}, + {{0x3ff89f84, 0x25c71e14, 0x1285ed45, 0x1b7ac971, 0x01061268, 0x31db457d, 0x1d9b936c, 0x02d4f797, 0x3b0f}}}, + /* 11*16^2*G: */ + {{{0x246c7ecb, 0x20c4c377, 0x1bb4ce97, 0x0ebb4ff9, 0x26e1ec9d, 0x3bdccd21, 0x34181c81, 0x32bacf40, 0x6e2a}}, + {{0x2ebc8720, 0x1124807b, 0x367512c8, 0x31c1ae46, 0x3b643afa, 0x03136bc3, 0x3ee149d8, 0x2919e5fb, 0x9e61}}}, + /* 13*16^2*G: */ + {{{0x30a4147e, 0x2dc063cf, 0x375f201e, 0x11f762fd, 0x090a5827, 0x05c5fa29, 0x1156baf6, 0x0124ba7a, 0xd5a7}}, + {{0x33fb65ff, 0x392cf2e0, 0x167f57f8, 0x3136611e, 0x1e0532f4, 0x242641d9, 0x389c6fc4, 0x09bd76ea, 0x9db5}}}, + /* 15*16^2*G: */ + {{{0x18edcec6, 0x3b76d1af, 0x3634f454, 0x018730b4, 0x2cdac6a1, 0x0fbf18c0, 0x18ba8052, 0x0466aaf8, 0x38c5}}, + {{0x1933db08, 0x15b82fec, 0x35530a64, 0x285b208a, 0x1f282f28, 0x32cb689d, 0x1732a668, 0x3748a176, 0xe649}}} + }, + { + /* 1*16^3*G: */ + {{{0x11e5b739, 0x0ff396d5, 0x12222ed7, 0x2e4e0cff, 0x3c846de0, 0x26731b1b, 0x3865a72f, 0x0567dca2, 0x175e}}, + {{0x29fed695, 0x3be9bffb, 0x124345c6, 0x2d6556b7, 0x371f5eac, 0x3e5e947f, 0x079eba4e, 0x1b83678f, 0xd350}}}, + /* 3*16^3*G: */ + {{{0x05041216, 0x16dfe3c7, 0x02b836a6, 0x1ccd7da1, 0x2fed523f, 0x2d67bf70, 0x3acf4128, 0x0c5ec87d, 0xda75}}, + {{0x2e708572, 0x2bb4ca61, 0x37acedad, 0x2ab01eb9, 0x2d7fc6e9, 0x27886cd0, 0x2d5f0df1, 0x2811afdc, 0x73f8}}}, + /* 5*16^3*G: */ + {{{0x2465a930, 0x0050f9c7, 0x31352fdb, 0x21fc705a, 0x02eb1e25, 0x0f16312a, 0x349d7057, 0x316d23a5, 0x1c71}}, + {{0x034638b5, 0x361cfdb3, 0x3174d471, 0x0d178fed, 0x0bb68c79, 0x0fc7ca09, 0x1fa0c271, 0x30cd3a3d, 0x4a91}}}, + /* 7*16^3*G: */ + {{{0x3adb6ee7, 0x0c636b96, 0x344a077e, 0x143750c9, 0x1b4c9c78, 0x3a0dea42, 0x1a566936, 0x12bf07cc, 0xd84e}}, + {{0x142ebed2, 0x0b555b9b, 0x2a3e6498, 0x362b25d2, 0x25de4dfd, 0x0e3563d5, 0x379ce12a, 0x20269f1e, 0xe525}}}, + /* 9*16^3*G: */ + {{{0x249e6d10, 0x253a7b3e, 0x2ac99d23, 0x02b7fceb, 0x3f6ed3f6, 0x08ae4a17, 0x2814d41b, 0x1112f799, 0xf3d4}}, + {{0x1347da3f, 0x280e3301, 0x29d6c630, 0x06b69433, 0x0a4b5bfc, 0x2e56b066, 0x0163d4ba, 0x0937e9bc, 0x0a43}}}, + /* 11*16^3*G: */ + {{{0x29d33a07, 0x232cd01b, 0x239bcab4, 0x1cbb822a, 0x3df4044e, 0x21548336, 0x01d89f90, 0x194b2767, 0xae30}}, + {{0x20a0b2a6, 0x121c303d, 0x3d7e95c7, 0x270dfd77, 0x38d5cf1c, 0x339f4cf6, 0x3fe57efc, 0x3670e358, 0x6cb9}}}, + /* 13*16^3*G: */ + {{{0x0c28caca, 0x165952e4, 0x08281da7, 0x1a71eef3, 0x388c9a18, 0x05f9d60c, 0x1e1c815e, 0x06ca96f5, 0xd8dc}}, + {{0x23b3ec7a, 0x36d9dba8, 0x08128f6c, 0x0c574b3b, 0x247d947d, 0x36369080, 0x2c7d58c6, 0x02b649f3, 0x8cec}}}, + /* 15*16^3*G: */ + {{{0x3bc4416f, 0x2487ed98, 0x30b04028, 0x2bbf48fc, 0x32f31da7, 0x1096a340, 0x04eccd59, 0x38a4b17e, 0x2749}}, + {{0x3c6bbd8e, 0x3a62f78b, 0x2e961057, 0x27a7ed97, 0x0adb3ef5, 0x3652643f, 0x32bc4403, 0x0b538dd9, 0x50cc}}} + }, + { + /* 1*16^4*G: */ + {{{0x03ff4640, 0x09aeb63e, 0x1552ffe5, 0x11071f95, 0x262ee053, 0x3ab016d8, 0x00c9c99c, 0x243511ec, 0x363d}}, + {{0x3bee9de9, 0x0800f1fc, 0x0199ecb6, 0x2e6a2402, 0x33363145, 0x2d114e5f, 0x32221953, 0x1ceb7f1c, 0x04e2}}}, + /* 3*16^4*G: */ + {{{0x36e55dc8, 0x2e24485b, 0x2ca04394, 0x3e56adba, 0x1094426f, 0x12910301, 0x1ffb2ba8, 0x1011e431, 0x4431}}, + {{0x1be323b3, 0x076512bb, 0x2aa2e503, 0x1a8a6de7, 0x02fed7a6, 0x260dfd59, 0x366f8fe9, 0x3050b994, 0x96b0}}}, + /* 5*16^4*G: */ + {{{0x301b23a8, 0x3fa52175, 0x287ee0ad, 0x1edf51c2, 0x21089dab, 0x090f56e4, 0x0a87c126, 0x3fa3619b, 0x9e22}}, + {{0x0884edae, 0x1e904f14, 0x3511cecf, 0x3df2527e, 0x1c1533c0, 0x3cfc0826, 0x22d10177, 0x3c3a7284, 0xfd2f}}}, + /* 7*16^4*G: */ + {{{0x071a70e4, 0x35d022fc, 0x35cf475d, 0x17b947d7, 0x05306dcd, 0x35a7991c, 0x22a8d2ed, 0x3db540f3, 0x508d}}, + {{0x29950984, 0x3cb96fdc, 0x28aadfed, 0x300c8a3b, 0x3e49c54e, 0x0c12a9cc, 0x3c42d777, 0x10e6e4ce, 0x154c}}}, + /* 9*16^4*G: */ + {{{0x0e1abe11, 0x3abf69db, 0x1cb220f6, 0x2e487096, 0x0125b2da, 0x37d6064c, 0x09763338, 0x3fe11544, 0xe3db}}, + {{0x1fa8de63, 0x2d26b552, 0x06b5c414, 0x325f640f, 0x0a8ef3d3, 0x23e9d76e, 0x01421643, 0x3e42668d, 0x06f2}}}, + /* 11*16^4*G: */ + {{{0x03593449, 0x33c6c8d8, 0x02a46ffd, 0x06df04b9, 0x3d014af6, 0x36704e81, 0x2940d878, 0x381931f7, 0x19ac}}, + {{0x2df83631, 0x29052e4e, 0x084068a3, 0x1c42e7d0, 0x002c46ac, 0x2f5ce765, 0x0a333bfe, 0x2480d49a, 0xe379}}}, + /* 13*16^4*G: */ + {{{0x0cba6b63, 0x38fa624b, 0x10b3bb5e, 0x03f99d3f, 0x288e310a, 0x30cc8a3a, 0x07daa108, 0x033b083e, 0xd874}}, + {{0x2934c5f3, 0x3ba8db01, 0x381694ab, 0x0413d730, 0x3ac37d40, 0x29bba640, 0x132bf378, 0x304cf1ae, 0x6472}}}, + /* 15*16^4*G: */ + {{{0x1b3ec038, 0x0653fcb0, 0x20c6b276, 0x3f545ab9, 0x290a50d9, 0x20f9d8bc, 0x06083648, 0x0cce46d4, 0x58ac}}, + {{0x10246279, 0x1baa8fc4, 0x34fbbca1, 0x06410f02, 0x11fe9702, 0x1e4927a6, 0x092d9787, 0x35c1b557, 0x9163}}} + }, + { + /* 1*16^5*G: */ + {{{0x1ffdf80c, 0x27de6957, 0x15bcd1b6, 0x3929e068, 0x05638843, 0x0912d6dd, 0x3c2be8c6, 0x17c5977c, 0x8b4b}}, + {{0x1fd4fd36, 0x0fbfc319, 0x162ee56b, 0x38cd9518, 0x30da04f9, 0x2f5e04ea, 0x308b4b3f, 0x029bda34, 0x4aad}}}, + /* 3*16^5*G: */ + {{{0x355812dd, 0x028a960b, 0x12d30e2a, 0x1119c8d5, 0x18f78e3d, 0x2afb5b01, 0x3352f0b6, 0x2f5ea4bf, 0x7029}}, + {{0x1a2d2927, 0x087319ac, 0x3b2c73c7, 0x36ba1090, 0x0683ac47, 0x19512b8c, 0x0b3d27dd, 0x3eb6bf7a, 0xb0ee}}}, + /* 5*16^5*G: */ + {{{0x3d486ed1, 0x27395a0e, 0x1565b6a4, 0x116fae92, 0x0f756057, 0x35042763, 0x25c99009, 0x3b72bab9, 0x9ccf}}, + {{0x35e95d8d, 0x3db567b5, 0x1592aa24, 0x0859d65a, 0x0b341124, 0x08920480, 0x232cfb61, 0x135c4f5a, 0x7c2f}}}, + /* 7*16^5*G: */ + {{{0x1bd0eaca, 0x081ac69d, 0x22d4ab7a, 0x31d15dae, 0x24df19d0, 0x23f78cf2, 0x1414335a, 0x12e1d8d0, 0xcd9a}}, + {{0x2bff4acc, 0x39bebed6, 0x16f634f6, 0x09ece3bb, 0x3ea08b01, 0x1222ba4c, 0x0f23e815, 0x161e687a, 0xf045}}}, + /* 9*16^5*G: */ + {{{0x07bc57c6, 0x08254e8f, 0x2b276cbf, 0x00f5e88f, 0x16309449, 0x3cb4ba4f, 0x19bea884, 0x220be23b, 0xad09}}, + {{0x2e4a0ab8, 0x28cb03b6, 0x190e2d3c, 0x0c474dcd, 0x1abe5f7b, 0x061b1ca7, 0x3a52ba28, 0x302310be, 0x7243}}}, + /* 11*16^5*G: */ + {{{0x2ba56302, 0x2a0c31ca, 0x30f1862e, 0x01aa4deb, 0x3ad2e0f5, 0x368b4aa7, 0x0a41f1ea, 0x0a42bacf, 0xd9d1}}, + {{0x08291c29, 0x2ab76bea, 0x3a74f2ae, 0x0e6bb367, 0x2386e417, 0x1c5719c9, 0x13eed029, 0x0c44fb0b, 0x7eb5}}}, + /* 13*16^5*G: */ + {{{0x34d1243a, 0x2b34dc13, 0x354a5fdb, 0x2c49808f, 0x3f558402, 0x3486b018, 0x16cef91c, 0x1e7794e7, 0xbc50}}, + {{0x055db68a, 0x172545a2, 0x1f47169f, 0x1fb93d6c, 0x3fc8d75f, 0x31cae537, 0x05cbb8ee, 0x0a8ece9c, 0x6506}}}, + /* 15*16^5*G: */ + {{{0x374a3f9f, 0x2349139a, 0x00981690, 0x21e99977, 0x32625ac2, 0x37aab9f6, 0x3c7e8913, 0x29df9417, 0x4d31}}, + {{0x301e0ba7, 0x3f2c0904, 0x2e00a754, 0x3dbed46d, 0x002753cb, 0x063ce31e, 0x0575b06b, 0x07b25826, 0x2224}}} + }, + { + /* 1*16^6*G: */ + {{{0x1232fcda, 0x2d845649, 0x2c0e77bc, 0x0036ffe9, 0x1548c7b7, 0x1dc7002f, 0x3996d6bf, 0x2ea9b976, 0x723c}}, + {{0x1eb39f5f, 0x07701a76, 0x37949480, 0x1828194d, 0x024d6e26, 0x044dd222, 0x0c498a92, 0x19ed5657, 0x96e8}}}, + /* 3*16^6*G: */ + {{{0x00633cb1, 0x159f827a, 0x1d021132, 0x168892da, 0x181fcb57, 0x189cc848, 0x2cad400c, 0x273cc5ea, 0x6dde}}, + {{0x27ce6b34, 0x1f7526a9, 0x3859ef35, 0x2c9ff6b3, 0x3a66a880, 0x27be1a86, 0x3e41d5c9, 0x3ef9e9c1, 0x9188}}}, + /* 5*16^6*G: */ + {{{0x2933f3c5, 0x06694634, 0x1f125224, 0x1683dc45, 0x07b85008, 0x12edfe39, 0x1cde813c, 0x29cb356d, 0x486f}}, + {{0x0afb0f53, 0x2b529c6b, 0x30f23b79, 0x366de0f3, 0x08f19f62, 0x3122ebb3, 0x3dd43e48, 0x08c67d5a, 0x62e1}}}, + /* 7*16^6*G: */ + {{{0x1e99f728, 0x2f565089, 0x2f12204e, 0x1cdd7ef9, 0x2a530367, 0x13fc9edd, 0x0af4fb66, 0x1a5d2a25, 0x2479}}, + {{0x2baaebff, 0x1e80145b, 0x175a2d83, 0x36fcf025, 0x0d664a5a, 0x0ba1f9f6, 0x33001ec5, 0x23511a23, 0xe3d7}}}, + /* 9*16^6*G: */ + {{{0x2fb0079a, 0x27831b50, 0x3926049c, 0x1be7bdc8, 0x33832491, 0x2967b9da, 0x15ff0631, 0x32f6a8f5, 0x2f39}}, + {{0x2c5690ba, 0x388a5cc0, 0x02a0230f, 0x3ecfef22, 0x0da58b9b, 0x24db409e, 0x239834da, 0x36f784e1, 0xabea}}}, + /* 11*16^6*G: */ + {{{0x24f7ab73, 0x24cc02cb, 0x14443a77, 0x38f53aa7, 0x34aed262, 0x0e7a1b14, 0x161ba56a, 0x075b0c9f, 0xe5a3}}, + {{0x30561f42, 0x244e8ff1, 0x00cba213, 0x2311126a, 0x0ece5dbf, 0x062a5de9, 0x29d7a0c1, 0x230f6347, 0x3778}}}, + /* 13*16^6*G: */ + {{{0x014dcd86, 0x23e4a68f, 0x2bf71b58, 0x31750825, 0x11dcf11f, 0x03766081, 0x13447df5, 0x27528345, 0xcc38}}, + {{0x08f0a873, 0x23adb767, 0x27e78746, 0x315f863f, 0x2910ca05, 0x1a2f6efa, 0x2bbed9b5, 0x13f5983d, 0x93ae}}}, + /* 15*16^6*G: */ + {{{0x38819311, 0x13e71bad, 0x08771472, 0x0f87b884, 0x35ed1f0b, 0x0285f833, 0x1e902375, 0x2472275c, 0x7f92}}, + {{0x2c2eb125, 0x2a7e6d5e, 0x086a174a, 0x02aa9027, 0x2415b612, 0x037a3114, 0x03ef0f5d, 0x034418fb, 0x9da0}}} + }, + { + /* 1*16^7*G: */ + {{{0x0e7dd7fa, 0x294cfb28, 0x3a919839, 0x11e5848d, 0x02d3b509, 0x3fbb204b, 0x2bf98ba5, 0x293524ef, 0xeebf}}, + {{0x21de8999, 0x37f53f6b, 0x311f712d, 0x393370e9, 0x38089d9a, 0x39fb6bc5, 0x2f0f269e, 0x2328e5c3, 0x5d9a}}}, + /* 3*16^7*G: */ + {{{0x3b7ceceb, 0x0fd9e3fe, 0x097faf0f, 0x2967e4e2, 0x2e681473, 0x3ee049bd, 0x2d45036f, 0x2188109d, 0x437a}}, + {{0x16c181e1, 0x0d8ef30d, 0x08f97827, 0x0883f3f7, 0x1297ff87, 0x23fada67, 0x2c32f69b, 0x1ae84fba, 0x0b91}}}, + /* 5*16^7*G: */ + {{{0x097f96f2, 0x1635ca78, 0x2c8735cd, 0x208d4a74, 0x3cc27335, 0x2df8ee68, 0x089bc83c, 0x27c4f8a9, 0xa9ef}}, + {{0x16c04be4, 0x00f556c1, 0x29b4702c, 0x13e26bd6, 0x3b613db7, 0x1bb8583a, 0x19d7cd95, 0x33396515, 0xe814}}}, + /* 7*16^7*G: */ + {{{0x350cf77e, 0x302ad684, 0x0a8ab0db, 0x36fd5d15, 0x2a064207, 0x209f5a7e, 0x135be553, 0x01507b87, 0x66d8}}, + {{0x20eaa3a6, 0x297e5ebe, 0x3b1b76d2, 0x112d0ead, 0x1613f694, 0x0750814d, 0x3fb42c3f, 0x37f9ccbf, 0x51cf}}}, + /* 9*16^7*G: */ + {{{0x07213a5a, 0x0d5218a2, 0x05fa62b9, 0x1cc8129e, 0x0cc3c80b, 0x14228719, 0x03fa2bf3, 0x01784d94, 0x62ac}}, + {{0x346a9e45, 0x04348703, 0x17994efc, 0x16424060, 0x292579e5, 0x179e781e, 0x1a6e4d39, 0x2f7ce834, 0x236f}}}, + /* 11*16^7*G: */ + {{{0x27bad12b, 0x0c3f5261, 0x2f66e1ec, 0x357a803a, 0x2f2db385, 0x184ebd71, 0x08f5b5bf, 0x31125c91, 0xca13}}, + {{0x1723b0f2, 0x25a67d1a, 0x1a575668, 0x1c2adc44, 0x2da3d663, 0x17e993aa, 0x287c8ac1, 0x0260d870, 0x83aa}}}, + /* 13*16^7*G: */ + {{{0x1c80414e, 0x36bb97e5, 0x166cf7fd, 0x3be2a18b, 0x209e4914, 0x04713d11, 0x12ae85ac, 0x2c4069c1, 0x1cec}}, + {{0x12169a3b, 0x32ba524b, 0x07231d0d, 0x1d55f951, 0x2dad1690, 0x2a8ca0d7, 0x17cfb4e5, 0x1819a582, 0xf343}}}, + /* 15*16^7*G: */ + {{{0x0ed810a9, 0x13d6f231, 0x0700155c, 0x22274fcf, 0x1f23924f, 0x036bd7c7, 0x38f9cc95, 0x241d4135, 0x2a69}}, + {{0x3a9b4728, 0x3e1ace23, 0x2c145c7c, 0x1f51fa5f, 0x3b04fc66, 0x3161a553, 0x1ffdac3e, 0x00e6db0f, 0x54f9}}} + }, + { + /* 1*16^8*G: */ + {{{0x39a48db0, 0x3f5e0d6c, 0x33c03bfe, 0x048568a6, 0x3bde459f, 0x0742826d, 0x27167279, 0x11369a5b, 0x100f}}, + {{0x2bc65a09, 0x3ef57358, 0x35195ac0, 0x3fd2863f, 0x090666b7, 0x23ccc030, 0x00b772ec, 0x384c64a8, 0xcdd9}}}, + /* 3*16^8*G: */ + {{{0x15bc15b4, 0x32e684d2, 0x25a2ee69, 0x1d40a391, 0x17ca8d92, 0x163ba73b, 0x2adc9ed8, 0x038b947b, 0x10e9}}, + {{0x18aa258d, 0x13af9825, 0x2bb6a883, 0x296258c0, 0x2d1f754c, 0x1ea3185a, 0x1e0424d5, 0x0dc0e035, 0xc68a}}}, + /* 5*16^8*G: */ + {{{0x3fe75269, 0x374ff0c0, 0x13d33182, 0x1de8f301, 0x0b7dcda3, 0x16e42dc5, 0x01638457, 0x0bd0b695, 0xf742}}, + {{0x17e49bd5, 0x22603a1c, 0x0a398e01, 0x2ce88dfd, 0x3635977f, 0x339f72e7, 0x3093fd18, 0x0bc68cc4, 0x406c}}}, + /* 7*16^8*G: */ + {{{0x35a7175f, 0x14ed9a5b, 0x31cf42a6, 0x2e39dc74, 0x15debbed, 0x1e69560b, 0x03cff728, 0x2b4105f5, 0x2d8c}}, + {{0x3b9d592a, 0x3cdeee46, 0x0b5e5e0c, 0x211aff67, 0x2c9d377a, 0x08cbe984, 0x0a94a7bb, 0x0ee0cc63, 0xc73f}}}, + /* 9*16^8*G: */ + {{{0x14b51045, 0x0d326f0e, 0x31c25b3e, 0x31b225bc, 0x28cf73bb, 0x1cf53ac7, 0x26ea58ae, 0x3f476e62, 0x1ecb}}, + {{0x02c70026, 0x0e99c404, 0x036422d5, 0x240191ad, 0x1a9b38b1, 0x342ec612, 0x1c3a6447, 0x388c22e6, 0x1cf6}}}, + /* 11*16^8*G: */ + {{{0x29358533, 0x1eb35d9b, 0x0fb4b9df, 0x2a4cfe75, 0x132a8c10, 0x25568a47, 0x3752883e, 0x25317f95, 0x9a08}}, + {{0x0360ba08, 0x2cf87177, 0x380ddadf, 0x29b96f6e, 0x0fc32165, 0x05f57e55, 0x38fc31f9, 0x20f10806, 0xa798}}}, + /* 13*16^8*G: */ + {{{0x198ef7f6, 0x25101758, 0x2078f9f6, 0x08fcfdde, 0x38aea659, 0x272149ce, 0x3d2e35bd, 0x361276d3, 0x664d}}, + {{0x1d1eac94, 0x1d25bfcd, 0x38e6ecee, 0x0f4eacc6, 0x0458cffc, 0x12339774, 0x27932a14, 0x0805c5fc, 0xad51}}}, + /* 15*16^8*G: */ + {{{0x03c934b3, 0x03029adf, 0x30ae2c4e, 0x0c7d6016, 0x11a7022b, 0x07659a60, 0x0b863823, 0x0ea4ddf4, 0x8211}}, + {{0x042c6a0f, 0x1f9798ab, 0x24468037, 0x07df09a6, 0x20c628aa, 0x19b3cad6, 0x23666084, 0x2e36b26b, 0x8da1}}} + }, + { + /* 1*16^9*G: */ + {{{0x2534fd2d, 0x322b379b, 0x0f3b3852, 0x1fe35119, 0x04c017a7, 0x2489e928, 0x3ed1b1dc, 0x06f898b1, 0xe103}}, + {{0x1456a00d, 0x113c63ca, 0x21ced79a, 0x24b75067, 0x17535af2, 0x1a905d96, 0x0405e6bb, 0x1864a250, 0x9d70}}}, + /* 3*16^9*G: */ + {{{0x2f028d83, 0x1e588ebb, 0x27439615, 0x25649b6e, 0x1e69db61, 0x2af96857, 0x385ec6a5, 0x3df138f1, 0xa7eb}}, + {{0x19d0bed1, 0x1900e4ae, 0x30539199, 0x28e249d2, 0x04804b47, 0x271cddc1, 0x362d5cfd, 0x054beff8, 0x6205}}}, + /* 5*16^9*G: */ + {{{0x27dd5cfa, 0x2b839008, 0x309d4b5b, 0x227144df, 0x2346336a, 0x31a94d09, 0x24f4c1cd, 0x282372c0, 0x5b5c}}, + {{0x1e48e98c, 0x19929be6, 0x33269d3e, 0x3419f32b, 0x069094bf, 0x07c33aa2, 0x15825e99, 0x2dbdc2a8, 0x3ecc}}}, + /* 7*16^9*G: */ + {{{0x23531f82, 0x2e54a38c, 0x10c2c9f2, 0x144c9aec, 0x022c29ff, 0x3cf9d227, 0x14bb5cce, 0x09ab3044, 0x046f}}, + {{0x0bceda07, 0x1417f22c, 0x2b55c7fa, 0x09651736, 0x032579d0, 0x0dc2b0bf, 0x382eace2, 0x12cc58d6, 0x6b80}}}, + /* 9*16^9*G: */ + {{{0x10432711, 0x02c550dc, 0x1916b906, 0x0502cbf7, 0x19645acf, 0x25bc3c22, 0x0efb535f, 0x09b64c78, 0xc119}}, + {{0x2fe2610c, 0x1249878b, 0x0f34055e, 0x2ae48b28, 0x0cc6cf83, 0x252fc61b, 0x1b689184, 0x3e331f49, 0x8be1}}}, + /* 11*16^9*G: */ + {{{0x21257963, 0x05e61d3e, 0x34aa861c, 0x006354b0, 0x0979c45b, 0x2ed52d4e, 0x08f2e6cd, 0x11ba7ada, 0x6908}}, + {{0x066f9835, 0x295d9665, 0x1c92b253, 0x2f0f2a08, 0x2fbb7f6c, 0x05c093e4, 0x3ebc5b40, 0x17f2dfcf, 0xe248}}}, + /* 13*16^9*G: */ + {{{0x1ee23ace, 0x3444e52f, 0x14dd2fd2, 0x321f196d, 0x232915de, 0x1d54b7d2, 0x220babba, 0x3dfee324, 0xfb3d}}, + {{0x1722e8de, 0x0277bd32, 0x2d27f5ee, 0x1c9c50bf, 0x3ab58a9e, 0x09455036, 0x33c5652a, 0x0a6f0471, 0x510e}}}, + /* 15*16^9*G: */ + {{{0x10272351, 0x181f3fbd, 0x19ff1098, 0x1cd2cf7e, 0x31cd4170, 0x228facea, 0x0518b3eb, 0x17b093d7, 0x6dd8}}, + {{0x3fc7664b, 0x2c1fe8ad, 0x3e0817c9, 0x1f1bfdf0, 0x1c41b787, 0x101fe6bd, 0x3427e09d, 0x19fd0487, 0x16ea}}} + }, + { + /* 1*16^10*G: */ + {{{0x1094696d, 0x3579a236, 0x01d6af52, 0x3e2c99a9, 0x3bd7ec5c, 0x0a0e7c50, 0x15b530ac, 0x1b2b91b5, 0xfeea}}, + {{0x18090088, 0x05577afc, 0x041442d3, 0x072255f3, 0x3ecd5c98, 0x39384afc, 0x0e1bab06, 0x1adb25f7, 0xe57c}}}, + /* 3*16^10*G: */ + {{{0x08dfd587, 0x1e4d86ed, 0x1b026560, 0x312e8e32, 0x35a12d5e, 0x19eaa8b3, 0x0508b348, 0x2d06eb3d, 0x5084}}, + {{0x11470e89, 0x39e7a5fe, 0x091f5606, 0x2dbd581a, 0x2927475d, 0x2a9b2154, 0x00d31619, 0x18c68766, 0x34a9}}}, + /* 5*16^10*G: */ + {{{0x3ab34cc6, 0x0208c985, 0x0f30a12d, 0x030a5d9f, 0x0d7128c8, 0x2cfc7f46, 0x2d5ea53f, 0x300f8190, 0x4f14}}, + {{0x187e681f, 0x17b094be, 0x281dd022, 0x378f33a3, 0x262540b9, 0x0e9c3d0e, 0x0e894c65, 0x342a32a9, 0x7b53}}}, + /* 7*16^10*G: */ + {{{0x1241d90d, 0x109dc404, 0x32444f83, 0x073c5076, 0x1dd363e8, 0x10d8257b, 0x39ed1d41, 0x2e1f9271, 0xa74d}}, + {{0x3f7adad4, 0x0c9462e0, 0x0a0a313f, 0x3b9424d1, 0x0171c8a9, 0x37422962, 0x3eef327f, 0x24736bc8, 0xf786}}}, + /* 9*16^10*G: */ + {{{0x31c1ae1f, 0x17b32888, 0x2cd40b2a, 0x1b9631a2, 0x23565845, 0x373513ae, 0x2a2cf9ac, 0x3e95d12e, 0x6901}}, + {{0x122838b0, 0x3e0cc197, 0x1c77a930, 0x27cee979, 0x1c900dd7, 0x2d4e030a, 0x3c212461, 0x1722089c, 0x35de}}}, + /* 11*16^10*G: */ + {{{0x327a4bdb, 0x2c0c4206, 0x1494cac4, 0x1a9b410d, 0x3ba35d04, 0x12d90fc6, 0x38127a24, 0x360b4750, 0x8d3c}}, + {{0x269a8a2c, 0x0f4d31f3, 0x30ad296c, 0x38e01f4d, 0x36236ed4, 0x3efe7401, 0x241f470c, 0x0958603b, 0x9bd4}}}, + /* 13*16^10*G: */ + {{{0x34ec1d2d, 0x10334f1a, 0x27d8f454, 0x0267d71b, 0x3b691fd9, 0x2759ca59, 0x24739afe, 0x20d8f581, 0xeaf9}}, + {{0x0c838452, 0x33f9d581, 0x3e84b53f, 0x3d4b5515, 0x3199aaa9, 0x08a2839a, 0x38d22775, 0x060e9ff9, 0xe518}}}, + /* 15*16^10*G: */ + {{{0x045ae767, 0x32cd6fdc, 0x289771cb, 0x1cea72e7, 0x06e5d8c2, 0x103814b0, 0x1b63466f, 0x2f458ebb, 0xfb95}}, + {{0x3bbf0e11, 0x214fa82b, 0x259f1341, 0x05bd1c62, 0x02275bb8, 0x013674da, 0x0ddbc520, 0x0536046a, 0x664c}}} + }, + { + /* 1*16^11*G: */ + {{{0x01ec6cb1, 0x0fea5e2f, 0x08583de3, 0x3b595f60, 0x3fca3cfe, 0x1ef92f9b, 0x09cdcb36, 0x2a476441, 0xda67}}, + {{0x3a68be1d, 0x3a7aa389, 0x0f740a17, 0x31eb7142, 0x1780e5de, 0x118fdfb2, 0x242bc41f, 0x2a8d5205, 0x9bac}}}, + /* 3*16^11*G: */ + {{{0x15bc8a44, 0x3bf74194, 0x3e151a19, 0x10405df2, 0x1a5fc768, 0x159692e9, 0x0eda3d38, 0x20160f3f, 0x4d01}}, + {{0x1adbc09e, 0x3c7e5324, 0x182da362, 0x250811a1, 0x16381396, 0x26ea001f, 0x0f5d367e, 0x31b0632d, 0x3a33}}}, + /* 5*16^11*G: */ + {{{0x25daeb00, 0x306ad4a1, 0x2645f76b, 0x08fac933, 0x36e9d159, 0x32da89ce, 0x0f957082, 0x0541f7d7, 0x2f66}}, + {{0x033992c0, 0x089d9e26, 0x15d308c1, 0x337b89c6, 0x00add06e, 0x254dea08, 0x2b33f6ef, 0x0484dbd4, 0xfd5c}}}, + /* 7*16^11*G: */ + {{{0x116aa6d9, 0x20aa4282, 0x3702dcf1, 0x18b22d91, 0x035a3836, 0x3c5d3686, 0x247d2254, 0x045f417f, 0xf594}}, + {{0x3f2e50cf, 0x1f41a5ba, 0x26b5b86c, 0x249de20f, 0x14bceb7a, 0x176f6ac2, 0x31b12cf6, 0x18695ba5, 0xcaa7}}}, + /* 9*16^11*G: */ + {{{0x3ac6f4c0, 0x2ab80e55, 0x04bdc4cc, 0x13a37a33, 0x16711dda, 0x070e2f9a, 0x19cdec4e, 0x135fc7d3, 0x0f2d}}, + {{0x32339b58, 0x1f9eeeb5, 0x0242656e, 0x1a8429e4, 0x01e71e8f, 0x2c9ff7ce, 0x3de4d17f, 0x27e15fa4, 0x3ec8}}}, + /* 11*16^11*G: */ + {{{0x1f428cb2, 0x215414ff, 0x2a22b55d, 0x0e08bf59, 0x18d0f123, 0x1e860565, 0x14bbd1eb, 0x33b0b8a8, 0x1d5d}}, + {{0x095b189b, 0x397b4402, 0x36044a51, 0x0fa44be1, 0x2f0b88bd, 0x1e1e0921, 0x2c8c50d0, 0x1020ec50, 0x6e5c}}}, + /* 13*16^11*G: */ + {{{0x28381273, 0x2c3aa23e, 0x293dae5f, 0x10dda581, 0x0126ced8, 0x3aa6cb31, 0x167439fd, 0x28bf4c02, 0x89d9}}, + {{0x1309773d, 0x00facfbb, 0x1127324a, 0x1875a02b, 0x0f62f58f, 0x2abc81db, 0x26f50377, 0x096d1475, 0xdfca}}}, + /* 15*16^11*G: */ + {{{0x35c71d91, 0x330cacb2, 0x2894fd21, 0x25178b8a, 0x1afece23, 0x28704c45, 0x10ae1c52, 0x06e1e0e9, 0x8319}}, + {{0x22148a61, 0x02e7b023, 0x10445ee7, 0x2847d45d, 0x3cae8a17, 0x1b784f45, 0x01b709e0, 0x1fc55ce0, 0xe0ac}}} + }, + { + /* 1*16^12*G: */ + {{{0x1a37b7c0, 0x1d517330, 0x311069f5, 0x02343dee, 0x322151ec, 0x00024d7b, 0x34cdda6e, 0x13ea82cc, 0x5390}}, + {{0x022771c8, 0x372c25ac, 0x14434699, 0x26666078, 0x0d3c1c13, 0x27b32b08, 0x0106d88c, 0x21f42f20, 0x5bc0}}}, + /* 3*16^12*G: */ + {{{0x08a2050e, 0x06b10bf9, 0x15f8a677, 0x0bbd55d8, 0x079b8974, 0x1da731b9, 0x0731896b, 0x093f492f, 0x6737}}, + {{0x061d3d70, 0x24326924, 0x3349cc2b, 0x1aeb3f50, 0x086b6dbe, 0x120b026a, 0x24a20203, 0x2095e25a, 0xe4cf}}}, + /* 5*16^12*G: */ + {{{0x02de63bf, 0x2fdb920e, 0x3261c66c, 0x0ebd4ca1, 0x2166a8e0, 0x26298c7d, 0x34c309e5, 0x3be91cb7, 0x4366}}, + {{0x217924cd, 0x0b1a9023, 0x2aa6d6b0, 0x0ec31496, 0x0268eaf3, 0x094df84c, 0x2d7ce2ee, 0x36426fb8, 0x2e7d}}}, + /* 7*16^12*G: */ + {{{0x06f96190, 0x04149ffc, 0x3c9525ef, 0x3c0b7a41, 0x3aa75fd1, 0x3955a599, 0x1ab1f97b, 0x14d89e64, 0x7bd7}}, + {{0x2bda00f6, 0x0f45c812, 0x20ea695a, 0x03f31707, 0x3827d6ce, 0x3591d250, 0x26309d5e, 0x3cacf6ee, 0x8336}}}, + /* 9*16^12*G: */ + {{{0x16ad41ed, 0x0ec54c55, 0x0f035243, 0x022b0d7d, 0x18dc9203, 0x0d067a24, 0x2d5c1afa, 0x249ef76a, 0x4f7e}}, + {{0x3e642d57, 0x3d0d5e19, 0x2af775bd, 0x1cc51c53, 0x28f6a62e, 0x26037d4e, 0x08b10552, 0x1d1455aa, 0xdfe7}}}, + /* 11*16^12*G: */ + {{{0x27748690, 0x3e981449, 0x0630b01c, 0x15e41376, 0x133d007d, 0x114ac7b7, 0x11ccc94b, 0x32e19f4a, 0x2355}}, + {{0x0c89582b, 0x1f11d4c5, 0x11c93914, 0x0a1a1633, 0x2a7c5858, 0x2e17b056, 0x1e1f8f55, 0x3c62969c, 0x21c2}}}, + /* 13*16^12*G: */ + {{{0x0ade7f16, 0x36ba8858, 0x0be028c6, 0x272eba4f, 0x275d24ae, 0x164aadb0, 0x1a56c013, 0x2096e6cf, 0x0b66}}, + {{0x08c56217, 0x251109a1, 0x3e7cd2bd, 0x090f037c, 0x17a97fb7, 0x29daea2d, 0x09b3fef3, 0x282e0638, 0xa1fb}}}, + /* 15*16^12*G: */ + {{{0x19060d5b, 0x241ac08a, 0x03a3a7c2, 0x1184ec47, 0x3951cb90, 0x026cbf67, 0x1022cb61, 0x010f3c2f, 0xf602}}, + {{0x1af88f13, 0x1bdbd42c, 0x3dd1a3f7, 0x2a95b4ad, 0x0f7bea37, 0x2a3d92b1, 0x0cf19881, 0x2dc1b07c, 0xf036}}} + }, + { + /* 1*16^13*G: */ + {{{0x3ad86047, 0x3fe567d0, 0x29b8bcae, 0x2d4e810e, 0x0a906779, 0x3329dd93, 0x183a7719, 0x3342f4d6, 0x8e7b}}, + {{0x0460372a, 0x284011fa, 0x3fd68b3e, 0x3a238b91, 0x29514579, 0x0c410832, 0x1a4b3940, 0x1dc2ca8f, 0x10b7}}}, + /* 3*16^13*G: */ + {{{0x041ead4b, 0x3fa21e68, 0x11b03c1f, 0x1d7b7eda, 0x3e76be3a, 0x11cd3beb, 0x3337ec71, 0x03032323, 0xbfc9}}, + {{0x06fedaed, 0x114b1bc2, 0x2e0ae3e7, 0x11a3bfcc, 0x042d36fb, 0x29c63754, 0x0ded24db, 0x206c7827, 0x7a94}}}, + /* 5*16^13*G: */ + {{{0x35bb3b3e, 0x1b9ef41d, 0x39f73cb2, 0x1d4d85fb, 0x2d3f5b50, 0x1664fa30, 0x3aaa4dca, 0x3c472f8f, 0x732d}}, + {{0x17366693, 0x315df87b, 0x0c58436c, 0x276b5b59, 0x253916e6, 0x38956100, 0x39977cb7, 0x240fb7a3, 0x7f41}}}, + /* 7*16^13*G: */ + {{{0x088dc3b9, 0x17d6cf06, 0x1774c99c, 0x299a493a, 0x17ef6019, 0x2a210332, 0x147b428d, 0x252e580e, 0x4ce0}}, + {{0x25c0de52, 0x3053dedb, 0x1ea06502, 0x0816c832, 0x36aca216, 0x2d360329, 0x29b3ed57, 0x03eeafc6, 0x0539}}}, + /* 9*16^13*G: */ + {{{0x0aaafe5a, 0x30dd782c, 0x109aedd4, 0x151c2ce9, 0x023fd0e2, 0x229aa56c, 0x267de96d, 0x23addbf1, 0x9a96}}, + {{0x0ed975c0, 0x39aff509, 0x1e70cc0c, 0x2d620299, 0x061d0ee7, 0x319b40f6, 0x3ba2954f, 0x3ec1e9b4, 0xabf6}}}, + /* 11*16^13*G: */ + {{{0x334c6397, 0x1d472fe7, 0x074cd093, 0x374f6d40, 0x36b22107, 0x2bbe0094, 0x161954f0, 0x3efb405c, 0xd3c6}}, + {{0x28cb3f9c, 0x07f23415, 0x05e0e00b, 0x031dc224, 0x2ab6468a, 0x20e5364b, 0x22af1945, 0x34b15797, 0x4a0d}}}, + /* 13*16^13*G: */ + {{{0x0ac3137e, 0x26e0964c, 0x1af64461, 0x2496d8a9, 0x2b3953fe, 0x3c1a9daa, 0x243b8e02, 0x38e604a4, 0x4cbd}}, + {{0x2ec02fe6, 0x0023c573, 0x08ead60c, 0x24e9eb96, 0x14c370d1, 0x24a84d2e, 0x36159500, 0x151823c4, 0x6ce5}}}, + /* 15*16^13*G: */ + {{{0x20fbf84b, 0x1e88c1b3, 0x03f0b8a4, 0x3123f2ef, 0x14cebb03, 0x3671cc30, 0x16247b8b, 0x0ccf20ac, 0x4b9d}}, + {{0x236c3c48, 0x0e7b92d2, 0x2f5b5e62, 0x19b550f8, 0x39b7eb67, 0x04f66099, 0x0c152553, 0x31fef893, 0xfd7f}}} + }, + { + /* 1*16^14*G: */ + {{{0x19c43862, 0x2a107856, 0x397e6690, 0x29fd3c60, 0x381bde71, 0x02061a26, 0x1ff21e6d, 0x3b4d3073, 0x385e}}, + {{0x142e5453, 0x01163f95, 0x086dc8cc, 0x0c13bb08, 0x2bf4576b, 0x077867a7, 0x223f5670, 0x3af0fa3a, 0x283b}}}, + /* 3*16^14*G: */ + {{{0x36e2d9b3, 0x12f4c1aa, 0x338d6351, 0x36e4a0c6, 0x0f845641, 0x0ba984e7, 0x305e75e1, 0x053ce5f1, 0x19a3}}, + {{0x0baaaf33, 0x154bb897, 0x004be56d, 0x00874749, 0x3528b3a5, 0x2597e21f, 0x328dd234, 0x363d76b1, 0x6cac}}}, + /* 5*16^14*G: */ + {{{0x12f00480, 0x36161fac, 0x100dcee7, 0x0d620128, 0x36721920, 0x32618d93, 0x0daa355d, 0x3b52e56a, 0x5840}}, + {{0x3e22cf9e, 0x164b578a, 0x2ae38721, 0x1d489514, 0x1dd8daba, 0x1a37aa85, 0x3f141079, 0x369ac882, 0x670c}}}, + /* 7*16^14*G: */ + {{{0x23f54c42, 0x12137ba0, 0x29a3dc8e, 0x37068f09, 0x0e532545, 0x16307d3b, 0x118fb1dc, 0x00694d1a, 0x9f57}}, + {{0x2feb6a21, 0x18387124, 0x219e5278, 0x3b9e12ac, 0x29bfdd89, 0x256dad5c, 0x19e57bfb, 0x23ee2007, 0xce7b}}}, + /* 9*16^14*G: */ + {{{0x1522461a, 0x3a504cca, 0x3c718327, 0x2cc28996, 0x3ef9a0bc, 0x2e1c0419, 0x28cfc01b, 0x045a48d6, 0x27f6}}, + {{0x07301a2d, 0x2a932be7, 0x28639446, 0x2606c836, 0x028ee8e4, 0x2315849d, 0x26ad2ea4, 0x3c6a6402, 0xe512}}}, + /* 11*16^14*G: */ + {{{0x114f36b9, 0x338b26cb, 0x3b9f390c, 0x2632aed8, 0x34a98125, 0x2fcbd0d7, 0x2f941261, 0x1e615b3b, 0x6407}}, + {{0x24b4b50a, 0x252c7ba7, 0x19ceeb28, 0x36821c12, 0x1a7b6c8c, 0x035d7f61, 0x16efaef9, 0x24a3d139, 0xda61}}}, + /* 13*16^14*G: */ + {{{0x14d6b76f, 0x3bd8f7e6, 0x0c815dbc, 0x396a7eed, 0x1dfeae7f, 0x3dc22f02, 0x1669f452, 0x1438c721, 0xa237}}, + {{0x0dcca8da, 0x0764b332, 0x1b848d14, 0x1c1f047f, 0x011113e7, 0x0be8f935, 0x3de6dac3, 0x26c529b9, 0xf733}}}, + /* 15*16^14*G: */ + {{{0x3ceee475, 0x0bba7193, 0x0ed782b1, 0x1ab20a10, 0x0aff41ab, 0x0f0087cf, 0x2378d5ed, 0x2b01e8fc, 0xbbf1}}, + {{0x07fe5067, 0x1188a802, 0x38b41d68, 0x3ae76250, 0x315fe324, 0x20f320da, 0x060e6108, 0x2e37bab5, 0xb4bf}}} + }, + { + /* 1*16^15*G: */ + {{{0x03fac3a7, 0x181bb61b, 0x147fbc9c, 0x377e1296, 0x3dfa180f, 0x31ce9104, 0x0f191637, 0x366e00fb, 0x06f9}}, + {{0x3a842160, 0x21a24180, 0x0281002d, 0x29374bd7, 0x05c4d47e, 0x238a8c39, 0x059ba69b, 0x31a3980c, 0x7c80}}}, + /* 3*16^15*G: */ + {{{0x121ce204, 0x13b5d7a3, 0x26763d52, 0x29c96390, 0x26f72fb2, 0x1d361672, 0x3c64fb83, 0x107458ac, 0x43ca}}, + {{0x134a8f6b, 0x1494113a, 0x2a4a468e, 0x2db1eccf, 0x1ba31f9a, 0x143e4863, 0x023fa1c6, 0x16a0b8dc, 0xdcea}}}, + /* 5*16^15*G: */ + {{{0x2be6efda, 0x13f3a4b3, 0x07280596, 0x0b53fcfe, 0x1a506d92, 0x1bdc8de1, 0x12bf5b66, 0x01bbc8a2, 0x9c3e}}, + {{0x27aefc7d, 0x3c503cca, 0x336fdf7d, 0x0ef21a1e, 0x226fd5d4, 0x02cb5133, 0x2923d8af, 0x027979d8, 0xa7b7}}}, + /* 7*16^15*G: */ + {{{0x06c88be2, 0x2449ead7, 0x06ee5e27, 0x0b1e0834, 0x30775bea, 0x1c9d6760, 0x20f033bb, 0x22a8c4f8, 0x5d6f}}, + {{0x0d7ad75d, 0x24b954fc, 0x2bf92c28, 0x2adbe3a9, 0x08bc20ed, 0x2abcceac, 0x2d4e8c71, 0x2c636355, 0xadc4}}}, + /* 9*16^15*G: */ + {{{0x12d1b844, 0x0a24d46e, 0x173e484f, 0x2700e0b0, 0x388bc5c6, 0x2c570f04, 0x20d5fc86, 0x0d70c129, 0xf57d}}, + {{0x21266837, 0x192eaef5, 0x0915c6a4, 0x01a5c80c, 0x24634c70, 0x134fd6a7, 0x2f4d9790, 0x0f67aa63, 0x707f}}}, + /* 11*16^15*G: */ + {{{0x3cc7cb09, 0x0d3401fc, 0x1d1b4352, 0x31fada28, 0x1871463b, 0x1b87fb8f, 0x194a5f59, 0x181e8e99, 0x13e7}}, + {{0x08079160, 0x2f9d6a28, 0x2b576411, 0x3ab8aed9, 0x34299d65, 0x17f7616c, 0x3b8b1e32, 0x32237a3e, 0x284d}}}, + /* 13*16^15*G: */ + {{{0x18cdee05, 0x01833849, 0x32ec3b90, 0x1d87ec85, 0x06901da8, 0x00942c6c, 0x182e6240, 0x28c895a0, 0x29be}}, + {{0x262651c8, 0x39280d66, 0x0c698e39, 0x3f0c6db2, 0x305ec7f9, 0x026cfee1, 0x29a0ea90, 0x36689a43, 0x7c40}}}, + /* 15*16^15*G: */ + {{{0x12f18ada, 0x06db1d58, 0x3dbdbcc1, 0x182f64ee, 0x3d4a59d4, 0x0dbebfcc, 0x288e7d9c, 0x1e1b48e0, 0xf521}}, + {{0x23953516, 0x375a2bf4, 0x05bf0981, 0x17bd28db, 0x11d1d6aa, 0x09840af3, 0x0db57ecc, 0x1befd80e, 0xe068}}} + }, + { + /* 1*16^16*G: */ + {{{0x02d0e6bd, 0x0edf839d, 0x30f5e531, 0x1d3458f6, 0x0d6ecbf7, 0x0851f041, 0x04e2582a, 0x3500490f, 0x3322}}, + {{0x2c28b2a0, 0x13ce8ba5, 0x2873af62, 0x017d8fa8, 0x1af9b728, 0x0066f137, 0x24ef5bfb, 0x01e5fa59, 0x56e7}}}, + /* 3*16^16*G: */ + {{{0x059ab499, 0x2f674fc8, 0x273c330a, 0x04ca671b, 0x3f01bc0b, 0x065acf19, 0x005ba5d2, 0x2bfcc057, 0x78ba}}, + {{0x3ee097fd, 0x20748c63, 0x11251996, 0x18cbbba3, 0x02082e91, 0x2a1383b6, 0x2c0afafc, 0x3736f6c1, 0xad4b}}}, + /* 5*16^16*G: */ + {{{0x3d06ace6, 0x124f85b3, 0x03a20ca4, 0x1c26cdbe, 0x29ab1a23, 0x2e126124, 0x2e3d4c20, 0x3c846852, 0x6f70}}, + {{0x3602d5de, 0x122fb4d2, 0x25ac5ee0, 0x0ca559af, 0x399f5075, 0x1763cd1e, 0x27b736f9, 0x228c2500, 0x791e}}}, + /* 7*16^16*G: */ + {{{0x20ee1b40, 0x323b8fb9, 0x1e96247d, 0x3b5216dc, 0x03ccd48c, 0x2527c644, 0x2a415f80, 0x276ca75a, 0xe159}}, + {{0x178f93a6, 0x0758997b, 0x032999de, 0x0d8e9d2f, 0x2fc7cfa6, 0x3e252aa8, 0x1d4a0efa, 0x1888caa0, 0x7933}}}, + /* 9*16^16*G: */ + {{{0x09c00c3e, 0x2077e8a1, 0x11208e2f, 0x03a3c0f2, 0x051859f0, 0x158b4cf5, 0x06956436, 0x0125c110, 0xbb0b}}, + {{0x11955a35, 0x266a60b4, 0x05dc90a7, 0x19c113a4, 0x31b052fe, 0x34be85ea, 0x39f63655, 0x391614eb, 0x4067}}}, + /* 11*16^16*G: */ + {{{0x05dd32e6, 0x039d6e70, 0x13e5ee7e, 0x18ed546d, 0x1a5fbfc6, 0x1276f81d, 0x1789e9b6, 0x10555065, 0xdc5a}}, + {{0x354a99b9, 0x039f6de9, 0x2e49bcf8, 0x3cbba41d, 0x3f59442f, 0x3a978806, 0x367a76dc, 0x2a298fe7, 0x4af3}}}, + /* 13*16^16*G: */ + {{{0x0544e7cb, 0x3b516eb1, 0x12960359, 0x0190896d, 0x014e99a1, 0x0d5295c4, 0x33b9dbe3, 0x065c0e61, 0x156e}}, + {{0x2d250a37, 0x354e4b02, 0x2b439cd6, 0x25b56357, 0x034be894, 0x255ca98e, 0x1907da93, 0x2367e3cc, 0x6bc0}}}, + /* 15*16^16*G: */ + {{{0x059853ca, 0x2fef0a73, 0x319bf54d, 0x3a589ae7, 0x27161348, 0x29da88a3, 0x043826bc, 0x2f33b2da, 0x4269}}, + {{0x35b8d367, 0x2a563bd4, 0x1e5a8a3d, 0x0e50297e, 0x31a409fd, 0x2132a710, 0x016b723c, 0x0706a0b0, 0xed2b}}} + }, + { + /* 1*16^17*G: */ + {{{0x0134ab83, 0x0875d34a, 0x36433977, 0x06cfe6bd, 0x26586874, 0x05dc3625, 0x0b7da2bd, 0x0b1f4b78, 0x8567}}, + {{0x390313a6, 0x238c253d, 0x1298f44c, 0x1fc5ff31, 0x22c2e5e7, 0x10126fe9, 0x3b2eb637, 0x06e6d6d0, 0x7c48}}}, + /* 3*16^17*G: */ + {{{0x03ba9000, 0x37c1c8ea, 0x025e8b6f, 0x21cbe71a, 0x00143dc4, 0x21d81d61, 0x1d8c1684, 0x1d3e7ffc, 0xac38}}, + {{0x2f10cf0a, 0x368f1f65, 0x366e9fa4, 0x178d435f, 0x117f9308, 0x0b77a250, 0x1c069b86, 0x3a48c228, 0xaa65}}}, + /* 5*16^17*G: */ + {{{0x2d06dbd4, 0x2981bd9b, 0x0a20d081, 0x038fe15e, 0x23e729ec, 0x0501d7a6, 0x070139ad, 0x1739ea9a, 0x570d}}, + {{0x3d1ed495, 0x2996fb3a, 0x2460bed5, 0x20e8db71, 0x101bbbb6, 0x19b99c47, 0x202f605b, 0x14d25083, 0xa6ae}}}, + /* 7*16^17*G: */ + {{{0x092d230e, 0x0d307e48, 0x29339284, 0x3b8ca834, 0x366ef5da, 0x308a7b80, 0x28bb6f87, 0x3e1c0a09, 0x75b5}}, + {{0x151570b8, 0x0df2f7ef, 0x111f8fb0, 0x19e92c01, 0x1dfa8e02, 0x1e1d1553, 0x3852363d, 0x338878e9, 0x527c}}}, + /* 9*16^17*G: */ + {{{0x034fcc0e, 0x1edafdab, 0x3e3884c4, 0x1fc4290a, 0x1259c892, 0x16e0389f, 0x1dec2b0a, 0x23beb87b, 0x44fc}}, + {{0x319c420a, 0x33fc0c79, 0x0d0489d9, 0x03a5292f, 0x33d3d772, 0x099f9e20, 0x31367e49, 0x37a52ea6, 0xd2c7}}}, + /* 11*16^17*G: */ + {{{0x0bb69991, 0x169207f2, 0x3307175d, 0x3ecfe8b0, 0x02f535ff, 0x28598838, 0x27bc6866, 0x2e91eeb3, 0xdea2}}, + {{0x316fe2df, 0x019d0aa7, 0x21ed9bc7, 0x27736cd8, 0x37b9e722, 0x32ffb213, 0x028e4ac5, 0x2ff5b643, 0xae28}}}, + /* 13*16^17*G: */ + {{{0x114fc9cc, 0x30903409, 0x1a461658, 0x3402af0a, 0x38a83626, 0x073db312, 0x168d6efc, 0x3f2629b8, 0x3968}}, + {{0x1fad37dd, 0x064e5225, 0x388f3340, 0x05195dbf, 0x2d32c91a, 0x1e60b46a, 0x35928123, 0x2ef436d2, 0x789c}}}, + /* 15*16^17*G: */ + {{{0x2e0c85f1, 0x2bb08646, 0x03a3a250, 0x294b94d8, 0x3945d5a6, 0x0977c255, 0x06a2926b, 0x2441a638, 0x6896}}, + {{0x2dc1de21, 0x31d208cc, 0x0d503922, 0x10306768, 0x05d72d1f, 0x0c170761, 0x0979256f, 0x0fed2ce3, 0xaefd}}} + }, + { + /* 1*16^18*G: */ + {{{0x20c82a0a, 0x3f6566bd, 0x3668832f, 0x2489b183, 0x1413b10f, 0x1b27c646, 0x188a46b0, 0x2fe026c6, 0x0948}}, + {{0x18c8e589, 0x132dfe23, 0x17cd2bed, 0x137fc232, 0x03418c6d, 0x2dd31747, 0x36646dc6, 0x18a15b72, 0x53a5}}}, + /* 3*16^18*G: */ + {{{0x38c8ac7f, 0x0a0bf97e, 0x1e2aa527, 0x0490bb99, 0x16f84964, 0x0ce5b481, 0x22bbcb5c, 0x2cbef8e0, 0x9945}}, + {{0x29aea3b0, 0x1b650e85, 0x2dacdfa9, 0x0bde88fb, 0x28eff528, 0x36d13fec, 0x3282d607, 0x3b6092c3, 0x3eef}}}, + /* 5*16^18*G: */ + {{{0x169e353a, 0x3475e78e, 0x2bbe1f6e, 0x28110214, 0x07d5fe10, 0x3e0889c4, 0x070e6235, 0x131ac816, 0x2a31}}, + {{0x25746067, 0x09649b87, 0x32658bfc, 0x22952ab6, 0x2a1ba013, 0x18f91dae, 0x227ac1a4, 0x2b02fcd6, 0x15a4}}}, + /* 7*16^18*G: */ + {{{0x29b84966, 0x278bd27b, 0x17f3ff98, 0x13d041b7, 0x2b6c911b, 0x2dbebce9, 0x3fc2d498, 0x29402dc0, 0x5959}}, + {{0x07473a6a, 0x02998c86, 0x0fe24264, 0x00373023, 0x082a7091, 0x0c4a0837, 0x0a897f94, 0x399d07d7, 0x0370}}}, + /* 9*16^18*G: */ + {{{0x2bc6b173, 0x2c326e48, 0x2ed3feb3, 0x36188f1f, 0x1b5f9d7d, 0x183118c1, 0x22fe8e11, 0x0c4e4dc8, 0x9eeb}}, + {{0x1723a71d, 0x14e58836, 0x0e70c4b9, 0x29c6afb4, 0x3a1ae30e, 0x2aaff6ee, 0x2d58d952, 0x3c780443, 0xe121}}}, + /* 11*16^18*G: */ + {{{0x3ec805f3, 0x1dc910fd, 0x1d995915, 0x3903dd42, 0x2e97887d, 0x2ec8e201, 0x318f516e, 0x13f931fd, 0x39cc}}, + {{0x3a3c48d3, 0x06468304, 0x3c912e4d, 0x2e55cdcf, 0x02de7dbb, 0x399a4f3d, 0x2f8f3151, 0x11cb1691, 0xecb1}}}, + /* 13*16^18*G: */ + {{{0x0e22580e, 0x0f58bed7, 0x2d6f8879, 0x04ca25b4, 0x1bd4d2c7, 0x0bff7993, 0x0dc69689, 0x201d19bb, 0xf94c}}, + {{0x3127db82, 0x07948fd9, 0x2371d4e8, 0x21fb114c, 0x1a81f698, 0x12ffdaad, 0x1225a919, 0x1ff719e1, 0x5e9c}}}, + /* 15*16^18*G: */ + {{{0x10c4f21f, 0x2f902eb4, 0x103da7a6, 0x092a5653, 0x1999d250, 0x0081a36c, 0x1d162fcc, 0x2e1b1ab5, 0x8ccc}}, + {{0x329dfea0, 0x1fc49ba9, 0x264be28f, 0x24b72b20, 0x0758a54b, 0x2fbd5272, 0x11c43699, 0x2596189d, 0x57f8}}} + }, + { + /* 1*16^19*G: */ + {{{0x338fd8e8, 0x33b36067, 0x069752ac, 0x2c39137f, 0x2873a8f1, 0x19f383c0, 0x001c34f0, 0x339fd186, 0x6260}}, + {{0x32b4ae17, 0x06a13a56, 0x051c198c, 0x34a488e0, 0x2a1ef7ec, 0x024125dd, 0x1b571a7f, 0x2a0adbe9, 0xbc2d}}}, + /* 3*16^19*G: */ + {{{0x01136602, 0x2c2e9195, 0x19e3a5bb, 0x311bd203, 0x333b3d38, 0x1624dfc8, 0x2dfc33d0, 0x09ca0120, 0x87d1}}, + {{0x18af6aac, 0x3da0f107, 0x3d3bf7c4, 0x2a211d1b, 0x27745387, 0x289db3fd, 0x203de926, 0x0921c296, 0x71ce}}}, + /* 5*16^19*G: */ + {{{0x08c5a916, 0x2c8175cd, 0x35610f25, 0x17110354, 0x354aa13f, 0x2b318f6a, 0x1e9746b0, 0x1f4ff898, 0xfd5d}}, + {{0x3adb8bda, 0x052cdec1, 0x1cf6faab, 0x35ce052f, 0x07b52fe5, 0x10f299e7, 0x15b07d2b, 0x0fb43bad, 0x0dd8}}}, + /* 7*16^19*G: */ + {{{0x35f7529c, 0x17664258, 0x1bd51dd4, 0x1d96e62d, 0x34438138, 0x114f0cb4, 0x026122ba, 0x35042607, 0xde0d}}, + {{0x24cd88fe, 0x0f08300b, 0x09b77406, 0x224931a2, 0x3a357017, 0x042608b5, 0x2145f9b2, 0x1ba74428, 0xd70a}}}, + /* 9*16^19*G: */ + {{{0x38f76d11, 0x320bd234, 0x38515573, 0x044003ef, 0x0292a215, 0x16fbf0e7, 0x0f44e69c, 0x0822b693, 0xb26c}}, + {{0x23b7356b, 0x307002c7, 0x182624bd, 0x000c1967, 0x0d643305, 0x13a1f643, 0x1d33cf0c, 0x3e208252, 0x1f1c}}}, + /* 11*16^19*G: */ + {{{0x269e22db, 0x2538ec19, 0x39c8933f, 0x264ffd67, 0x0c294eac, 0x0ef4a406, 0x3f523a7e, 0x052e3f1f, 0xfceb}}, + {{0x1c2260a1, 0x3d5cb6c9, 0x24ebe4cb, 0x15439e4e, 0x1f0924ad, 0x22969d49, 0x2b8d1fcd, 0x1ace9035, 0x64aa}}}, + /* 13*16^19*G: */ + {{{0x238a2755, 0x3c2105e6, 0x149c5506, 0x1c869c59, 0x107faa53, 0x05d5dd2d, 0x15cac55c, 0x26988f33, 0x4e90}}, + {{0x23cca3de, 0x3de927d8, 0x229800ca, 0x3354e534, 0x3559dbb6, 0x091b7541, 0x235aecef, 0x36a1e333, 0xae56}}}, + /* 15*16^19*G: */ + {{{0x183ba64d, 0x20962566, 0x0c595a3a, 0x3983dde2, 0x0e40e2bd, 0x028517ae, 0x04c03bfb, 0x115708b8, 0xc367}}, + {{0x2a2181fd, 0x053323e5, 0x1778f146, 0x189aab28, 0x1964c742, 0x3839ba13, 0x36033080, 0x02b41a72, 0x3a52}}} + }, + { + /* 1*16^20*G: */ + {{{0x2037fa2d, 0x254f3234, 0x1bfdc432, 0x0fb23d5d, 0x3f410304, 0x0d21052e, 0x1d8d43d8, 0x1f782bf0, 0xe503}}, + {{0x1d755bda, 0x03977210, 0x0481f10e, 0x17d6c0fb, 0x190bddbd, 0x263427ee, 0x0d3b5f9f, 0x14d2eaa5, 0x4571}}}, + /* 3*16^20*G: */ + {{{0x177e7775, 0x222a29b8, 0x0ed95f63, 0x385564e2, 0x1291aeb5, 0x150eeb3d, 0x233cee58, 0x1a8ebfe5, 0x9d89}}, + {{0x3a056691, 0x3f3db4ea, 0x299253be, 0x26735fb8, 0x10927de8, 0x2593b5c9, 0x1bf0b94e, 0x2a790fd2, 0xdd91}}}, + /* 5*16^20*G: */ + {{{0x3c2a3293, 0x3f781378, 0x103476c5, 0x222e1bba, 0x02f4cd56, 0x2c295cca, 0x23792d0e, 0x2e3b9c45, 0x8327}}, + {{0x0e0df9bd, 0x2f215386, 0x2326a416, 0x2bf6ad3b, 0x39708496, 0x2cfa9989, 0x0a98e18b, 0x1f899bb8, 0x0499}}}, + /* 7*16^20*G: */ + {{{0x0562c042, 0x1086c9b1, 0x38dfb1a2, 0x0b48c8d2, 0x1a8ed609, 0x1998763e, 0x1b16897d, 0x0aaa8a9b, 0x5ae4}}, + {{0x0f79269c, 0x2417337e, 0x07cd8dbf, 0x3836e544, 0x389d4a94, 0x30777180, 0x3051eab5, 0x0e9f017f, 0x99d9}}}, + /* 9*16^20*G: */ + {{{0x1e85af61, 0x0d2204a1, 0x14ae766b, 0x23b5c8b7, 0x021b0f4e, 0x3ada3fdb, 0x1c8eb59a, 0x0eb909a8, 0x92c2}}, + {{0x036a2b09, 0x39c8d9a7, 0x2286fed4, 0x08eb60ad, 0x38d5792d, 0x085f571c, 0x11bb409f, 0x3e23c055, 0x414c}}}, + /* 11*16^20*G: */ + {{{0x07b5eba8, 0x38abc6cb, 0x118ea36c, 0x2afb71fe, 0x38df422d, 0x03d05dab, 0x3df1088d, 0x18231dab, 0xfee5}}, + {{0x0d0b9b5c, 0x3d4574da, 0x39054793, 0x203fd0af, 0x07c14ee3, 0x100be64a, 0x258afb11, 0x16644d3f, 0x3807}}}, + /* 13*16^20*G: */ + {{{0x3c63caf4, 0x078ee92c, 0x0f53d528, 0x23fceaca, 0x2a6afca2, 0x044ed318, 0x267e620a, 0x113ae4b9, 0x42e5}}, + {{0x169c29c8, 0x21ebb026, 0x3efc5f11, 0x29439eda, 0x015e7873, 0x3c88305d, 0x0c671f71, 0x15383e47, 0x9ff8}}}, + /* 15*16^20*G: */ + {{{0x1e0f09a1, 0x028af661, 0x14032838, 0x28427c6e, 0x300efef0, 0x25bb4a91, 0x32ce3839, 0x20ed9954, 0x7aed}}, + {{0x05857d73, 0x1176337a, 0x33f4a540, 0x22cbcc03, 0x032d8ed8, 0x2bf42ac4, 0x1ef7c7dd, 0x1517e68c, 0xf5b8}}} + }, + { + /* 1*16^21*G: */ + {{{0x24fce725, 0x1619a82b, 0x2a6c5b72, 0x3a36f471, 0x1771b4e7, 0x2a417a3c, 0x207adf5e, 0x1cac3d28, 0xe063}}, + {{0x0eee31dd, 0x09c0d3e5, 0x3104870b, 0x12129de1, 0x1a488cd7, 0x09eecab5, 0x18cfe12a, 0x225d2f38, 0x7a90}}}, + /* 3*16^21*G: */ + {{{0x1a328d6a, 0x2eaa0623, 0x1adc18bd, 0x135dcea5, 0x308fa7b2, 0x1a264616, 0x34e00a34, 0x3016e988, 0xc663}}, + {{0x3ec9b8c0, 0x0ec2edaa, 0x12bf9cc2, 0x21547a94, 0x171317dd, 0x2bf73c9d, 0x21c38d39, 0x3a6357dc, 0x3331}}}, + /* 5*16^21*G: */ + {{{0x3996de2f, 0x32472120, 0x0b25114b, 0x33b7cbb8, 0x0fe4e977, 0x2cc37ba8, 0x06a459ce, 0x09a0b7ee, 0xd3fc}}, + {{0x14526f8c, 0x31248907, 0x37abf168, 0x166d2637, 0x3781da4e, 0x2d1d5353, 0x30a18f68, 0x37e66917, 0xc4f0}}}, + /* 7*16^21*G: */ + {{{0x03e697ea, 0x31b12344, 0x05f83e85, 0x399e3ee6, 0x3fabd19c, 0x287fb268, 0x2c0237dc, 0x12d0ffac, 0xc17a}}, + {{0x1edc6c87, 0x3b8ee1f7, 0x39f02ab0, 0x38686d5f, 0x201fae96, 0x05e3dc65, 0x35954cae, 0x170b556a, 0x3935}}}, + /* 9*16^21*G: */ + {{{0x3163da1b, 0x0b4b0c08, 0x393a3118, 0x03b7b983, 0x011fde9a, 0x24d275ff, 0x390b468c, 0x22df2899, 0x8f61}}, + {{0x03bdd76e, 0x1fcc4844, 0x249b6e7c, 0x14319a8c, 0x2c5a4264, 0x2f69d35e, 0x3eb6eb5f, 0x0fc97c22, 0x7823}}}, + /* 11*16^21*G: */ + {{{0x0ec8ae90, 0x3a1643f8, 0x0bbc5dee, 0x2c9ae4ba, 0x03f1b8cf, 0x356e36b2, 0x21e6eb86, 0x303c56de, 0x9798}}, + {{0x252844d3, 0x2a6b0bab, 0x03188e27, 0x392596f4, 0x1c73bee2, 0x3b25253e, 0x02ed3dd2, 0x38aa9d69, 0xba40}}}, + /* 13*16^21*G: */ + {{{0x11d66b7f, 0x16865e3c, 0x187dc810, 0x29a49414, 0x1284757a, 0x3c6e42e2, 0x22d6747c, 0x1bb8fed6, 0xfdfa}}, + {{0x38e5178b, 0x2aa3e019, 0x3d78de9d, 0x11be7744, 0x1a18c4d8, 0x0307268f, 0x198db93c, 0x3cc78892, 0x4d9c}}}, + /* 15*16^21*G: */ + {{{0x1265bcf0, 0x201d5e12, 0x11c7d30b, 0x338ade10, 0x0f220e69, 0x3aa69187, 0x29e43add, 0x338e3788, 0xfd58}}, + {{0x2b996292, 0x0cf9ea73, 0x0f1cd1df, 0x0986ff8a, 0x05e4fb87, 0x20aae692, 0x3215bd53, 0x29794dd8, 0xffe0}}} + }, + { + /* 1*16^22*G: */ + {{{0x10559754, 0x02b5a423, 0x2a3f5854, 0x2c42f778, 0x0ce02204, 0x02efe770, 0x1d45358d, 0x1e9c5735, 0x213c}}, + {{0x34b458f2, 0x3fcb09d4, 0x36a7eedd, 0x12143d7c, 0x1ba190bb, 0x0eb41891, 0x06250701, 0x2b42d6b9, 0x4b6d}}}, + /* 3*16^22*G: */ + {{{0x1e05dccc, 0x0cb60046, 0x019a93e5, 0x0fe8fb53, 0x13d172ae, 0x1b825ae5, 0x1a030954, 0x3db85d4f, 0xb8ce}}, + {{0x0c6d5750, 0x0052833f, 0x26b68133, 0x1d5ff0da, 0x12bd99df, 0x3529d393, 0x09bbf6a4, 0x229829b3, 0x302b}}}, + /* 5*16^22*G: */ + {{{0x373bb31a, 0x16f7fb84, 0x3db97b48, 0x07dedad7, 0x3b5f4970, 0x282f78ba, 0x07385e02, 0x0cf9de6d, 0x03fb}}, + {{0x3d215c9e, 0x0d32f9a5, 0x07640d4e, 0x169f1db1, 0x3b572bc6, 0x30586aae, 0x2fe281e0, 0x36549523, 0xf36a}}}, + /* 7*16^22*G: */ + {{{0x1d9a4ab4, 0x16d457af, 0x15bb7c0a, 0x1f0db061, 0x0f7a3671, 0x05bded34, 0x03e1161f, 0x1f34427b, 0x4b17}}, + {{0x235ab6f7, 0x2ab77f91, 0x1741f558, 0x0df8957c, 0x226b486e, 0x23d9ca4d, 0x2fa65fda, 0x19ba6978, 0x3ec9}}}, + /* 9*16^22*G: */ + {{{0x301c23a4, 0x3d1beca6, 0x3a49cf56, 0x0a905611, 0x39cd75c2, 0x00e0a6e6, 0x27a06c2a, 0x00d481a8, 0x5e87}}, + {{0x10d986f9, 0x085e65ac, 0x24ccfda1, 0x05c761d2, 0x2c6e2da2, 0x1d5746b8, 0x09221e71, 0x1913bee7, 0x5b96}}}, + /* 11*16^22*G: */ + {{{0x007b0c66, 0x3cfcd748, 0x16c86fb1, 0x29ffb919, 0x2ceb7434, 0x08913d82, 0x1680a447, 0x30c064c3, 0xe545}}, + {{0x31f2d470, 0x21fd5f49, 0x35a239dd, 0x3960a386, 0x19bcbf97, 0x31bf68e5, 0x2955e7e5, 0x0d03a318, 0xe06a}}}, + /* 13*16^22*G: */ + {{{0x03648bba, 0x2960642e, 0x1c3c7444, 0x283c2c1a, 0x01b39882, 0x0fb8897c, 0x0f580a13, 0x10855e95, 0xb2a4}}, + {{0x00fb6452, 0x11bead28, 0x09c17bb2, 0x36154547, 0x3d7e31c0, 0x3ef25e3e, 0x366619e9, 0x17f0ada4, 0xfe4f}}}, + /* 15*16^22*G: */ + {{{0x2bab27d0, 0x3db748bb, 0x045103fc, 0x02d07e8b, 0x197007f7, 0x25c06463, 0x138651ba, 0x2383cf51, 0x1b90}}, + {{0x00d3d110, 0x07a19d79, 0x07e51b57, 0x2ef2a4d6, 0x3c4b9ab5, 0x15f24605, 0x26b5e6f3, 0x1897bb11, 0x9b6d}}} + }, + { + /* 1*16^23*G: */ + {{{0x08fbd53c, 0x0330e8ec, 0x1c62cddf, 0x20e31c2b, 0x019a87e2, 0x2e4d4a95, 0x0b34e8db, 0x09ca9ebd, 0x4e7c}}, + {{0x17dcaae6, 0x02ce5060, 0x3f7dd33e, 0x02e5852f, 0x2f681b53, 0x3f427db7, 0x10b18e16, 0x271d9b27, 0x1774}}}, + /* 3*16^23*G: */ + {{{0x2521b3ff, 0x38a61193, 0x1aa750ce, 0x0f01c5fa, 0x2e24a523, 0x1134afa6, 0x1455c75e, 0x138c0432, 0x0248}}, + {{0x0269da7e, 0x306b92e4, 0x23ac8bbc, 0x1c01b7a4, 0x2d0eebad, 0x30acf0ac, 0x3e30d07e, 0x34282a88, 0x9619}}}, + /* 5*16^23*G: */ + {{{0x004ba7b9, 0x25ade7ea, 0x0741751f, 0x35a91c0c, 0x2c954e20, 0x26dc359c, 0x2ce57ef7, 0x3149b3ed, 0x16c1}}, + {{0x1c5bd741, 0x1d6f8e94, 0x1c9a9cc4, 0x1d57006f, 0x0a94deec, 0x189d1672, 0x31439062, 0x1fdf0d00, 0xdb15}}}, + /* 7*16^23*G: */ + {{{0x236683fa, 0x20d921ea, 0x0ec0825e, 0x2086d4e0, 0x127b6695, 0x22739dd1, 0x131af87a, 0x0f35d4fe, 0x0397}}, + {{0x3f4a577f, 0x3d7ecadd, 0x3e981ded, 0x1e213863, 0x35a26cd7, 0x384ad8ca, 0x0a3a3643, 0x168b30c3, 0x38cf}}}, + /* 9*16^23*G: */ + {{{0x00bf6f06, 0x202ce667, 0x1043b571, 0x0f04cc89, 0x20576571, 0x3013d2c0, 0x0f1511c2, 0x26ee9cbb, 0xba6a}}, + {{0x381db551, 0x0cafbdc1, 0x0697aafe, 0x17453deb, 0x18bd8e9e, 0x082fcb95, 0x211b0320, 0x078e2cd2, 0x1377}}}, + /* 11*16^23*G: */ + {{{0x31231a43, 0x347be7c1, 0x1ad43b9f, 0x35453599, 0x1e442f44, 0x3b654193, 0x04dd2d8a, 0x2f3309f3, 0x35c5}}, + {{0x1620c8f6, 0x36dcb914, 0x23cf0ae7, 0x3de93301, 0x3a589d4c, 0x396082db, 0x346ce734, 0x1d5c8ee5, 0x0e36}}}, + /* 13*16^23*G: */ + {{{0x3dd40609, 0x3d02f15b, 0x181cd76b, 0x10642603, 0x08356ac7, 0x0bc4bf16, 0x186bca12, 0x27091715, 0xfd47}}, + {{0x2a64ca53, 0x378bc4d9, 0x21ca4739, 0x04ebb5c9, 0x1841fd91, 0x2b5e90f2, 0x0afeff2c, 0x33ed49a5, 0x3069}}}, + /* 15*16^23*G: */ + {{{0x2b799a7f, 0x36dc0bd4, 0x3b8e8424, 0x062db354, 0x2c7d544f, 0x363ae6bc, 0x0d864bde, 0x000a8eb3, 0x6c40}}, + {{0x13c81e32, 0x2d7320b3, 0x20483f68, 0x1eaf5320, 0x1ddcbdc0, 0x2e0da838, 0x235be690, 0x37054c2d, 0x95c2}}} + }, + { + /* 1*16^24*G: */ + {{{0x00fb27b6, 0x0909f8a1, 0x24305763, 0x1b8f6caf, 0x286aa5c7, 0x08e2b585, 0x38b1b10f, 0x138f6f9d, 0xfea7}}, + {{0x323cb96f, 0x0074f6df, 0x33f7b777, 0x1ad65ae5, 0x36af9312, 0x19d37b32, 0x313297cf, 0x1a36e6c2, 0x6e05}}}, + /* 3*16^24*G: */ + {{{0x3e889756, 0x37606ba6, 0x3004bb25, 0x1ed9265e, 0x1899f3f2, 0x3365ec9c, 0x1fea8226, 0x22f0cc84, 0x762e}}, + {{0x3ca6b774, 0x17896781, 0x084fa5e2, 0x1cb6cc52, 0x02e34719, 0x3313c526, 0x3e97c3c7, 0x250982bc, 0xc028}}}, + /* 5*16^24*G: */ + {{{0x0975d2ea, 0x1bdd7a5c, 0x014e8ea2, 0x14ab3e84, 0x08f4a91e, 0x26f6ec8c, 0x095348e1, 0x1f51f7d8, 0xdf07}}, + {{0x31936f95, 0x28f0b678, 0x3bdd277a, 0x07b16e13, 0x22527c8a, 0x21097262, 0x37f4424c, 0x1ea2003b, 0xf861}}}, + /* 7*16^24*G: */ + {{{0x3c4c92d7, 0x2e1247ee, 0x14391b45, 0x36d35bb9, 0x0b142935, 0x1f7aa0cd, 0x3da032e1, 0x1f5d62f4, 0x9f3e}}, + {{0x314906dd, 0x32eeff3e, 0x294e1186, 0x0a88c0f5, 0x2b150245, 0x18ac872e, 0x1466b588, 0x2107a9df, 0xecd2}}}, + /* 9*16^24*G: */ + {{{0x32a8c483, 0x2b835cca, 0x1040ac35, 0x12c32231, 0x39528117, 0x230f48bb, 0x0cf9edc3, 0x1e575ed7, 0xa0cc}}, + {{0x12cc6ba9, 0x0259d156, 0x36936055, 0x0d23c6f7, 0x31df786b, 0x1d3f25c8, 0x3873ee23, 0x0048be2c, 0xabc3}}}, + /* 11*16^24*G: */ + {{{0x05dd3aee, 0x1c3c6daf, 0x396d2f21, 0x054ea2a3, 0x2976ca13, 0x08aa6b1a, 0x3c7cce0e, 0x14294554, 0x6d1c}}, + {{0x3df597f7, 0x3b8d5393, 0x0ed53adf, 0x078c42aa, 0x07d47485, 0x09c8008a, 0x3dfdc977, 0x052381aa, 0xafff}}}, + /* 13*16^24*G: */ + {{{0x24a6d0bb, 0x1e32a6df, 0x1a1afdc6, 0x274c48bd, 0x26418f65, 0x069b62a2, 0x3f9f3f31, 0x075862e5, 0x5e5f}}, + {{0x1033eaf9, 0x1a0e11e4, 0x06f653a1, 0x1557cb94, 0x2721da72, 0x3daf3413, 0x3e6f7358, 0x140ac1a9, 0xd7b1}}}, + /* 15*16^24*G: */ + {{{0x0f005e3f, 0x36a6d791, 0x2c39bd2d, 0x3da38c6f, 0x01a1495a, 0x0f2e6b38, 0x2427fffd, 0x229acf05, 0xf813}}, + {{0x2f357eb7, 0x0b5f8080, 0x14be2134, 0x3b106f55, 0x25cb51f4, 0x005795ea, 0x0ebd9f9d, 0x23cefbed, 0xca75}}} + }, + { + /* 1*16^25*G: */ + {{{0x17bdde39, 0x0b00a910, 0x36043295, 0x11385e6d, 0x1968d315, 0x095c3566, 0x3cf0e10a, 0x1044fd9d, 0x76e6}}, + {{0x1901ac01, 0x12c5d4b4, 0x16d2032b, 0x0a8cf4ad, 0x01f0d35e, 0x019b5c1a, 0x295cf577, 0x37e37b93, 0xc90d}}}, + /* 3*16^25*G: */ + {{{0x0078ee8d, 0x3c142473, 0x06919442, 0x2fc83394, 0x1b4ff64e, 0x3dc98eaa, 0x1a9be25f, 0x15eb6167, 0xd08e}}, + {{0x2da63e86, 0x265fd370, 0x022ed9de, 0x0fbdf3e5, 0x3e6df412, 0x05cbb9d5, 0x088d72d6, 0x25e612ad, 0x852e}}}, + /* 5*16^25*G: */ + {{{0x029129ec, 0x164519c1, 0x24825481, 0x2b8eb3c7, 0x131d080c, 0x22fa03b3, 0x04d275f5, 0x30217935, 0x7da6}}, + {{0x2cd9ff0e, 0x2d42bb8a, 0x0ca586ae, 0x12302195, 0x1627bf04, 0x34081d24, 0x01857511, 0x051aee7d, 0xf498}}}, + /* 7*16^25*G: */ + {{{0x11654f22, 0x3e0f5255, 0x31aaee94, 0x3dfce508, 0x29d94fb2, 0x3a4006f9, 0x1be6e21b, 0x2433fd70, 0x90d0}}, + {{0x201a43e1, 0x3d77815d, 0x1a3f8740, 0x358d594f, 0x3f70336d, 0x3c08781a, 0x0f61a953, 0x26874aeb, 0xcd56}}}, + /* 9*16^25*G: */ + {{{0x076b19fa, 0x2dbbd947, 0x28819d71, 0x35b81b41, 0x21292ed9, 0x08b0c420, 0x1d1ecc73, 0x26161f3c, 0xda47}}, + {{0x326f5af7, 0x2a89bbac, 0x153fc206, 0x1ef44fa5, 0x16569ea6, 0x0da41df8, 0x0af01d17, 0x35de26f3, 0xebb1}}}, + /* 11*16^25*G: */ + {{{0x39135dbd, 0x364bed96, 0x1d8631ec, 0x3021ebce, 0x29897cf0, 0x1eabd60b, 0x1ee6ad81, 0x1d412a37, 0xe3e4}}, + {{0x0748045d, 0x241abcf9, 0x2c95da96, 0x2880bfd7, 0x383ffea5, 0x2320654a, 0x3c6c40b9, 0x16fe0272, 0x930a}}}, + /* 13*16^25*G: */ + {{{0x0dee455f, 0x2fc2e797, 0x0ce4075c, 0x19fff9ba, 0x0bdb4aff, 0x114ce3e0, 0x0a9b0a47, 0x195bfa1c, 0x7e8c}}, + {{0x171b9cba, 0x1cf7a660, 0x2f466271, 0x28b459d1, 0x03a53b4a, 0x3dd83d20, 0x0740f2a3, 0x318cb28c, 0xbddd}}}, + /* 15*16^25*G: */ + {{{0x2698b59e, 0x1de5ae6d, 0x13447a43, 0x0cd64962, 0x23c7260a, 0x2c0d6acf, 0x15eb15be, 0x107e246a, 0x3df8}}, + {{0x2b92baf5, 0x33e399e5, 0x14949f8b, 0x3f219ec8, 0x1cf3867b, 0x0aeba3c4, 0x090c1da0, 0x39b7e62c, 0xb38f}}} + }, + { + /* 1*16^26*G: */ + {{{0x2bcbb891, 0x2ac54090, 0x326cbee3, 0x1f3190f7, 0x3f8f9a8f, 0x206ea9d0, 0x2abe1e82, 0x315ac0ec, 0xc738}}, + {{0x299a84c3, 0x1f9cd765, 0x080cfe91, 0x0c53bbde, 0x3fbbbb82, 0x063cbab2, 0x2d2537f7, 0x2d5e2546, 0x893f}}}, + /* 3*16^26*G: */ + {{{0x0761d58d, 0x12eabcce, 0x0d60e2f3, 0x1326f902, 0x20df7aca, 0x09028d5c, 0x3614610a, 0x1849e08f, 0xb8c4}}, + {{0x1d1051a4, 0x0e3a82ea, 0x2107c5b6, 0x1d411e17, 0x33c5053f, 0x1163da5f, 0x0e37d14a, 0x365b145c, 0x8f9e}}}, + /* 5*16^26*G: */ + {{{0x050b0040, 0x36c2cc10, 0x0134adc2, 0x3d1f6e7c, 0x1a3671f3, 0x03264ffa, 0x271f7a35, 0x1ba7dc40, 0x08d5}}, + {{0x1b3fd0a1, 0x163899e9, 0x21782beb, 0x35f11c83, 0x39b285f6, 0x34542a35, 0x29aa21ff, 0x216baf42, 0xa121}}}, + /* 7*16^26*G: */ + {{{0x13573b7f, 0x15958f7c, 0x30b6270f, 0x268717b4, 0x265a3788, 0x083e5def, 0x3ce6341e, 0x3c8cb50b, 0xdc13}}, + {{0x0c1f2ba6, 0x0ab348a1, 0x3404b1c4, 0x11551c05, 0x290a7670, 0x10436a12, 0x2340c3c7, 0x2ea010a7, 0xc909}}}, + /* 9*16^26*G: */ + {{{0x07ae9ceb, 0x00bd642e, 0x0ef2d14b, 0x1b087a9c, 0x2119a822, 0x0655976c, 0x37f073af, 0x0b798077, 0x25c0}}, + {{0x0bc6e275, 0x1c24344d, 0x26587264, 0x319077c2, 0x2d11d537, 0x2138373e, 0x2383c0c8, 0x3ab4b204, 0x8a9f}}}, + /* 11*16^26*G: */ + {{{0x2c5a3c34, 0x3e0263db, 0x15949fe1, 0x33a0b00a, 0x2e3e58ae, 0x2e7d329e, 0x0e49ce8a, 0x2746cb3e, 0xfedd}}, + {{0x213d7714, 0x0ad52fd3, 0x1bf82976, 0x2bad51a6, 0x0f4b00ad, 0x3a14c4b2, 0x3b8e0b0b, 0x0930c614, 0xa52e}}}, + /* 13*16^26*G: */ + {{{0x2ab6a396, 0x2d395346, 0x11360769, 0x0086e468, 0x0488b373, 0x38b5fd7a, 0x2a48c2de, 0x0ca1af1b, 0x3e0e}}, + {{0x1980e27e, 0x3acc7923, 0x3468f6a2, 0x2c04107c, 0x053fc66a, 0x07f877ad, 0x337964f3, 0x205cbe8e, 0xca44}}}, + /* 15*16^26*G: */ + {{{0x341023ec, 0x2bcd6188, 0x3ecf570a, 0x11763ddb, 0x02b9af56, 0x0b808026, 0x32d28498, 0x2e4c2030, 0x344a}}, + {{0x1e1eeb87, 0x13e260a4, 0x03995d70, 0x13a5dabf, 0x114c5ffc, 0x23cb47a9, 0x0462a73f, 0x0ac10ac9, 0x6e1c}}} + }, + { + /* 1*16^27*G: */ + {{{0x08f6c14b, 0x1cba7d96, 0x29250143, 0x35cb97ce, 0x172877d1, 0x131d8df2, 0x25b81e26, 0x1899522d, 0xd895}}, + {{0x1d7d991f, 0x24d8fb5d, 0x3b067e17, 0x10a358ca, 0x0340eb03, 0x3b182063, 0x07eae728, 0x2a8e3caf, 0xfebf}}}, + /* 3*16^27*G: */ + {{{0x2127b756, 0x02ea1ffd, 0x3a097048, 0x10a2f92a, 0x20b41603, 0x0d8b6941, 0x1f12672d, 0x1e0bdc5b, 0x6d8c}}, + {{0x3f172571, 0x1547dd2a, 0x17cdcca6, 0x0ea9b68b, 0x134daf4e, 0x26a0b4db, 0x1b911145, 0x37c225bf, 0x99ae}}}, + /* 5*16^27*G: */ + {{{0x358cf17a, 0x37b869cd, 0x18823524, 0x3e1772e9, 0x0097f8f1, 0x166bbc6d, 0x37aca8d0, 0x2fb7656f, 0xebca}}, + {{0x1caa0ccd, 0x11b3717d, 0x0ace95c4, 0x3eb484b4, 0x032e6b10, 0x00286d9f, 0x2b9cb02c, 0x3383e3c8, 0x47d3}}}, + /* 7*16^27*G: */ + {{{0x2c855c5b, 0x33bb9456, 0x17c8afbb, 0x21588680, 0x17fc2811, 0x0c68da78, 0x0ce24453, 0x134b92f5, 0xe8df}}, + {{0x2e465650, 0x27579cb0, 0x21e4d7d5, 0x18ed57c7, 0x2f32c596, 0x136d3d67, 0x39b26444, 0x3f5c311f, 0x6c57}}}, + /* 9*16^27*G: */ + {{{0x12e7e454, 0x023d6f69, 0x30e6150d, 0x0cbbfbc3, 0x181662fe, 0x121808ea, 0x0a832912, 0x34f5c63b, 0x4068}}, + {{0x18ef191e, 0x1e6b3797, 0x3c373327, 0x23487b44, 0x1d38d198, 0x305165f6, 0x247aab9e, 0x14edc952, 0x8cd8}}}, + /* 11*16^27*G: */ + {{{0x06c5d939, 0x215eb7e1, 0x3a933de0, 0x1d68a1de, 0x0a027ea4, 0x2fccb983, 0x025e0b55, 0x03b36c76, 0x1255}}, + {{0x19e757c9, 0x0a9d3f15, 0x0d8d4319, 0x22dd07fb, 0x324a7283, 0x2390f05d, 0x2d7a7544, 0x20cd3e1c, 0x7b8f}}}, + /* 13*16^27*G: */ + {{{0x16c8a56f, 0x2342ab19, 0x0f374213, 0x024f150d, 0x3ad08f85, 0x2eded4eb, 0x185d4c69, 0x19c6b0ed, 0x944d}}, + {{0x1a7be289, 0x27d37197, 0x106517eb, 0x35305d37, 0x3ac61967, 0x10e4d84c, 0x01fff4c1, 0x1965ded4, 0xa710}}}, + /* 15*16^27*G: */ + {{{0x2e08f15a, 0x3bae2862, 0x012900ba, 0x1a795b72, 0x13c305fd, 0x2c0d956b, 0x19a0cfe6, 0x13a47342, 0x86a5}}, + {{0x01388308, 0x1493479f, 0x335254d3, 0x04a74496, 0x35686777, 0x0aa341b5, 0x384603a7, 0x18520de9, 0xcfee}}} + }, + { + /* 1*16^28*G: */ + {{{0x0f676e03, 0x24542959, 0x3e84edd4, 0x3ff1cda4, 0x1e8761ce, 0x3d90cd5c, 0x17518eb0, 0x2500caa5, 0xb8da}}, + {{0x0efdf6e7, 0x1223939d, 0x1ff3b511, 0x33161365, 0x2808b092, 0x267325d8, 0x1a1e4d7c, 0x37e91201, 0x2804}}}, + /* 3*16^28*G: */ + {{{0x06e1346b, 0x28661277, 0x05af1c5e, 0x2f9ec40e, 0x1152c05a, 0x31d87c53, 0x2d10be54, 0x1a3fc260, 0x0690}}, + {{0x17226c13, 0x2ed62953, 0x0c6026e7, 0x3da24e65, 0x06442aa4, 0x176caf42, 0x3de26da8, 0x38f8242f, 0xb863}}}, + /* 5*16^28*G: */ + {{{0x1ca1f6a1, 0x039a47f3, 0x08cff1a3, 0x232f450d, 0x286ce106, 0x1b7172c7, 0x19761528, 0x0d24f2c9, 0x898c}}, + {{0x164f647c, 0x12b7083c, 0x32bd79ca, 0x29f3e5e7, 0x2c6e93b2, 0x1150914a, 0x2a5549d8, 0x1661aad5, 0x75f7}}}, + /* 7*16^28*G: */ + {{{0x3d1e3998, 0x29a780f0, 0x3a04328a, 0x15b22e45, 0x2a274e5e, 0x0a675c08, 0x18bf01a5, 0x38bfb4a4, 0xb213}}, + {{0x325fb81e, 0x30b2f718, 0x3ded175e, 0x0d0596fa, 0x243bc3d5, 0x187afe0e, 0x13c12c3d, 0x23b083cb, 0x229f}}}, + /* 9*16^28*G: */ + {{{0x225be234, 0x02f87fb2, 0x1df35070, 0x20f8f9c3, 0x206e060e, 0x342e9a45, 0x3f93e5d1, 0x0eb605b1, 0x4b3b}}, + {{0x120e8362, 0x18edf80e, 0x3211b840, 0x39ff64b3, 0x0cc04c41, 0x17a5b7f6, 0x2bc9c787, 0x008ee176, 0x5eec}}}, + /* 11*16^28*G: */ + {{{0x2289f55e, 0x2598d29f, 0x2c76707b, 0x1dac3c38, 0x0965be29, 0x0946c09e, 0x04f96020, 0x222db76c, 0x9f7b}}, + {{0x3e1e4bde, 0x0f34ed97, 0x310a2b1b, 0x394db83a, 0x0fc71fc0, 0x051ad0a6, 0x010f7be3, 0x3de131c1, 0x32f9}}}, + /* 13*16^28*G: */ + {{{0x1dfe1d2b, 0x19527230, 0x16878e51, 0x24fd4279, 0x3b73a4c4, 0x332b7f4f, 0x048e3e76, 0x10fa72dd, 0xd58a}}, + {{0x0cd50922, 0x33c9e56e, 0x0bd6fbff, 0x366e8857, 0x28276b54, 0x1ca44ca0, 0x083cf10a, 0x219ae816, 0xfc17}}}, + /* 15*16^28*G: */ + {{{0x249c795e, 0x090546f8, 0x1ce805e1, 0x1101aaa6, 0x27ea4eed, 0x365a70f0, 0x18310cd6, 0x1c4e5c44, 0x21d2}}, + {{0x19208ece, 0x0004bb0e, 0x2dfb761b, 0x1c651292, 0x2bb4c3d6, 0x0d6e1548, 0x1acea177, 0x3e6d2c1d, 0x94c5}}} + }, + { + /* 1*16^29*G: */ + {{{0x23c0df5d, 0x06845de3, 0x156a792f, 0x067bfed4, 0x1d7fab20, 0x2b6ae51d, 0x3b33a7d8, 0x3a851107, 0xe80f}}, + {{0x2ac9ec78, 0x32d0a46d, 0x3322ea9f, 0x0557a02b, 0x0a94472d, 0x25da328f, 0x200771e8, 0x379fd8e3, 0xeed1}}}, + /* 3*16^29*G: */ + {{{0x17592d55, 0x300d67b3, 0x0e350192, 0x356e51d0, 0x3ce3b106, 0x3fbda58c, 0x1052608a, 0x31b6f128, 0x5d2e}}, + {{0x2f5183a7, 0x19b9743a, 0x11151742, 0x0a9ef36b, 0x0cd6950e, 0x1c43e89a, 0x245eb58f, 0x337e271b, 0x0a92}}}, + /* 5*16^29*G: */ + {{{0x3e8f9f5c, 0x247d2d27, 0x1880a519, 0x187c7856, 0x1f404d73, 0x32b8d085, 0x3f742fe2, 0x0770ec46, 0xac37}}, + {{0x325a503c, 0x1ea0ffcc, 0x2751e1d1, 0x254d163b, 0x14e73522, 0x04079cc9, 0x1a477ff2, 0x05b061c2, 0xc516}}}, + /* 7*16^29*G: */ + {{{0x19e33446, 0x12872354, 0x2af385df, 0x224ef114, 0x22a17a40, 0x2302f408, 0x1840c934, 0x000e853c, 0x8942}}, + {{0x26387689, 0x034e2803, 0x1e74f984, 0x3f5dcd9e, 0x3de4e06b, 0x2cb5b43b, 0x1077a4d8, 0x00e56569, 0xa9fd}}}, + /* 9*16^29*G: */ + {{{0x3913cb26, 0x35ca3256, 0x13bd6d03, 0x3ad06700, 0x105c9899, 0x36913fd5, 0x342a8a2c, 0x099acc28, 0x2770}}, + {{0x3348a7a2, 0x3f9c5ccf, 0x0815bebb, 0x103246f3, 0x32b324e9, 0x0b49341f, 0x0db1a555, 0x2f179e6c, 0xf649}}}, + /* 11*16^29*G: */ + {{{0x195e8247, 0x02aa8085, 0x286cd1af, 0x2ff71155, 0x38ba9097, 0x179b8073, 0x3ed2178e, 0x3434e0f2, 0x75e4}}, + {{0x19982d22, 0x288ff675, 0x29ad893c, 0x36ad6dba, 0x3726d47d, 0x3e5c3b1e, 0x10990741, 0x10a85d50, 0x1fce}}}, + /* 13*16^29*G: */ + {{{0x26333323, 0x11e7d136, 0x0f4abf47, 0x2eef071a, 0x04da849c, 0x08358166, 0x1bbf03f0, 0x2d8e0cd8, 0x3ed1}}, + {{0x35d61ba3, 0x2c4ff122, 0x378f7294, 0x2dca2842, 0x0f929ea9, 0x1f2625a2, 0x34ee75d9, 0x0b6922d6, 0xd84f}}}, + /* 15*16^29*G: */ + {{{0x333980bf, 0x09415f52, 0x0dd00baf, 0x28dc0b94, 0x08dd4368, 0x1bf5dc8d, 0x18181b84, 0x34bc1a9d, 0x70fd}}, + {{0x20b75785, 0x0bbaa33a, 0x1d74a561, 0x040d60e1, 0x2e596b0a, 0x29043447, 0x18696957, 0x32b03435, 0x5edf}}} + }, + { + /* 1*16^30*G: */ + {{{0x04e16070, 0x3701eef3, 0x2fd6915d, 0x286080c7, 0x167543f2, 0x29239475, 0x1704313b, 0x1a5ef7f3, 0xa301}}, + {{0x1e177ea1, 0x30346810, 0x0a11a130, 0x0d76fdf0, 0x140f9b17, 0x2027e897, 0x3e4f5081, 0x3e473ed9, 0x7370}}}, + /* 3*16^30*G: */ + {{{0x138011fc, 0x1c049c00, 0x17285626, 0x165a99eb, 0x200a4d83, 0x2c4cc208, 0x1eb11156, 0x04e8c205, 0x6e83}}, + {{0x3f15ab7d, 0x2b2da7e8, 0x1c51f9a6, 0x2be456ba, 0x1ac30426, 0x04b6c807, 0x0f204c1a, 0x2062f709, 0xc147}}}, + /* 5*16^30*G: */ + {{{0x100e6ba7, 0x0e9d26e3, 0x0916f7f5, 0x0dbb16d1, 0x19e1b43d, 0x0780e293, 0x0851f2bd, 0x2a4265e1, 0xf952}}, + {{0x0175e4c1, 0x36ebbb94, 0x062a2b98, 0x15c59ed3, 0x3fa0f655, 0x0dda8b89, 0x3cebf861, 0x0e96c22a, 0xd8a9}}}, + /* 7*16^30*G: */ + {{{0x03aa0e93, 0x2401968a, 0x2fb1f626, 0x0b8e50eb, 0x1e893a8f, 0x00c68676, 0x3fee7504, 0x1b578c74, 0x9401}}, + {{0x07addac2, 0x23bb49a2, 0x257b07a3, 0x210dceea, 0x2e6fd7f4, 0x1574d53b, 0x14d96403, 0x0cbb9711, 0x6750}}}, + /* 9*16^30*G: */ + {{{0x0266b17b, 0x03d218b8, 0x262bb32b, 0x0d5a2880, 0x1f09c202, 0x25e211aa, 0x3b2891bb, 0x345d3567, 0xef22}}, + {{0x39dac83e, 0x0a9b810d, 0x1c341b73, 0x39c9dbdc, 0x34a1073e, 0x27330eb8, 0x24c7568f, 0x21325eac, 0xbc57}}}, + /* 11*16^30*G: */ + {{{0x12d382a0, 0x0c4c056a, 0x2ecd9ae2, 0x2372ef38, 0x2df927f2, 0x2b31e02c, 0x3892d39c, 0x3bf3933a, 0xb5f7}}, + {{0x25b4b532, 0x28bc2aee, 0x1acf8c5b, 0x3ec25b4a, 0x0bddd371, 0x255f1b83, 0x3f2353c0, 0x1516d470, 0x6843}}}, + /* 13*16^30*G: */ + {{{0x012cffa5, 0x39a49191, 0x28cc5c47, 0x3b508219, 0x14624389, 0x1d5363ef, 0x31076408, 0x30f4acb9, 0x1cdd}}, + {{0x1521954e, 0x379b6273, 0x336b528a, 0x0726109a, 0x02b08ac4, 0x2c49afe5, 0x1f8a63fd, 0x1a832cbc, 0x1e47}}}, + /* 15*16^30*G: */ + {{{0x34a9f22f, 0x0d7f90e4, 0x17a8e2ad, 0x02067148, 0x0835b0cc, 0x3e2e2e52, 0x0e939f21, 0x2cd67c97, 0x2acc}}, + {{0x375c4927, 0x2dd772ce, 0x1ba550b7, 0x12f5efb1, 0x30edf115, 0x04e8dfb7, 0x2d2e5192, 0x293a5622, 0xd518}}} + }, + { + /* 1*16^31*G: */ + {{{0x3fb04ed4, 0x2deb18f8, 0x1307fffa, 0x330cc2c4, 0x278de208, 0x3e741449, 0x2b936463, 0x216ce275, 0x90ad}}, + {{0x0b6ef150, 0x24753523, 0x182894d9, 0x2bbeaf85, 0x3222b839, 0x372f6509, 0x38261aff, 0x1e8d8828, 0x0e50}}}, + /* 3*16^31*G: */ + {{{0x30b7b678, 0x09d76cce, 0x0f638166, 0x0f10c46f, 0x2b6c76f1, 0x21af2909, 0x0231ba19, 0x125ccd39, 0x186e}}, + {{0x38d91fc1, 0x1e81dbcb, 0x09535dca, 0x01dc8951, 0x37e67e11, 0x3f209702, 0x3bd84aa7, 0x18392601, 0xc0d4}}}, + /* 5*16^31*G: */ + {{{0x33421fb8, 0x3c1b972e, 0x35a55d0c, 0x125c7cbb, 0x37241298, 0x01acd30e, 0x1bf62e7e, 0x2360d3db, 0x061c}}, + {{0x0e3ccd80, 0x257bd9a1, 0x26fcdd29, 0x19c4d2ce, 0x05eb5c80, 0x0e496438, 0x3b4b7ba9, 0x1ab66400, 0x6dfc}}}, + /* 7*16^31*G: */ + {{{0x2f6b35a4, 0x0492f862, 0x327fb487, 0x27cde9aa, 0x3a68ad88, 0x18c901cc, 0x2e513b73, 0x2d8e8823, 0xf6a6}}, + {{0x01f422a6, 0x2badbfb2, 0x1ee1862c, 0x355d5b9d, 0x20186f19, 0x34dc13d5, 0x1138b1ca, 0x322a000b, 0x3df7}}}, + /* 9*16^31*G: */ + {{{0x26954c11, 0x25a08fa2, 0x160d018b, 0x2a290f05, 0x0778ff7f, 0x346c3c54, 0x2c376220, 0x3f0a30a1, 0x87a2}}, + {{0x272a8b45, 0x15b8ccb8, 0x278124b7, 0x1224cfca, 0x127532cc, 0x06523683, 0x2ecef97b, 0x1462d16a, 0x33ad}}}, + /* 11*16^31*G: */ + {{{0x22706ab6, 0x391d1cab, 0x2e53c0da, 0x02cd0774, 0x384cfe3c, 0x15bbf2f0, 0x081a6845, 0x0b811b9e, 0xe147}}, + {{0x1d58de05, 0x1ba1a85a, 0x13cd2753, 0x16275551, 0x0621f8aa, 0x1a465e32, 0x18fc683f, 0x24aa91f1, 0x82cd}}}, + /* 13*16^31*G: */ + {{{0x07a84fb6, 0x2feb9508, 0x3a15021e, 0x08da1d43, 0x08b9ebc4, 0x2d358079, 0x0aef5de8, 0x24b2013e, 0x1caf}}, + {{0x27149109, 0x1ac60640, 0x22ce6761, 0x07305a5a, 0x101622ec, 0x2993e3fc, 0x2e53a481, 0x2e16b25d, 0xbc24}}}, + /* 15*16^31*G: */ + {{{0x0a955911, 0x1da33f85, 0x0ded52db, 0x1f85a898, 0x17839710, 0x27bfa6cf, 0x1650d258, 0x3f5a6bc2, 0x705b}}, + {{0x3fd200e4, 0x2edf1a4f, 0x242e72d8, 0x1fced48a, 0x0051fa29, 0x18f607d5, 0x3f990a7e, 0x2904c2dc, 0xe14a}}} + }, + { + /* 1*16^32*G: */ + {{{0x1ec4c0da, 0x2ded1132, 0x23ea3351, 0x23159e1c, 0x1f162ee8, 0x2706b660, 0x35f33923, 0x2e74bd8e, 0x8f68}}, + {{0x101fff82, 0x08f2fde5, 0x1510bfdf, 0x3a8b3fa5, 0x3e215dbb, 0x36430ada, 0x23986de1, 0x27cb6e81, 0x662a}}}, + /* 3*16^32*G: */ + {{{0x123809fa, 0x238ae3b7, 0x1d954be1, 0x21172cd4, 0x051f08fd, 0x24cd8fc9, 0x09f228ba, 0x076f8b94, 0x3838}}, + {{0x331fed52, 0x35c1d460, 0x2d8f24db, 0x207f32cc, 0x0eb1cc36, 0x10169548, 0x117dcb09, 0x0b4283ee, 0xe4a3}}}, + /* 5*16^32*G: */ + {{{0x17c2a310, 0x3a909922, 0x01226303, 0x21aba950, 0x0699a1f1, 0x086e0aa9, 0x32ae6f69, 0x09c9390d, 0x4926}}, + {{0x1e27ded0, 0x3106da05, 0x35ff8ce0, 0x058d84a9, 0x14303b6d, 0x33e95a5c, 0x3abf95a2, 0x39dcef29, 0x1337}}}, + /* 7*16^32*G: */ + {{{0x0ebd2d31, 0x0e12c1e7, 0x306db8d1, 0x330695bf, 0x37e2f84d, 0x094ecf91, 0x00c90d5e, 0x15a30689, 0xe306}}, + {{0x12546e44, 0x24ad020e, 0x23738266, 0x2f2010af, 0x3d0db6ff, 0x3cac41fd, 0x34260888, 0x1bf8de24, 0x0eac}}}, + /* 9*16^32*G: */ + {{{0x363136b0, 0x14c30e78, 0x2b41dd9c, 0x3afe366a, 0x3bd63374, 0x2c39d88f, 0x0cefc271, 0x0403890a, 0x3b9e}}, + {{0x2cdbbc8a, 0x14fb05bd, 0x2d31f819, 0x2b8a28ce, 0x075b26a2, 0x14cfae3d, 0x2bb71df1, 0x26054b45, 0xfafb}}}, + /* 11*16^32*G: */ + {{{0x2f485d3f, 0x1823c11c, 0x107beee9, 0x3281da20, 0x1edef717, 0x1b2a03d7, 0x2c9a92b7, 0x2b525c4a, 0xbb0a}}, + {{0x3ca2f975, 0x1e4e4940, 0x1670bffe, 0x1696be8c, 0x17da3489, 0x34807dca, 0x354798ec, 0x2714f160, 0xea69}}}, + /* 13*16^32*G: */ + {{{0x36718dc9, 0x2bbb4ce8, 0x01123de4, 0x3962d36c, 0x3e0113e1, 0x23ac65eb, 0x2fcc0d4e, 0x02b2393b, 0x7909}}, + {{0x1cfae7c5, 0x18cc8ac4, 0x3a9008b9, 0x0dabedc2, 0x1aaa56dd, 0x205b2f36, 0x05b8f13d, 0x1c8ae464, 0xeaab}}}, + /* 15*16^32*G: */ + {{{0x3f60c7d1, 0x09a5a531, 0x1775ad2a, 0x35c779f3, 0x09ba668d, 0x0f6ef395, 0x17b551c0, 0x206b7a7e, 0xe77c}}, + {{0x02d72449, 0x3b1607ca, 0x02986d34, 0x051c3dc7, 0x28154363, 0x30ecc8fa, 0x01321c5f, 0x051e3bbe, 0x3acf}}} + }, + { + /* 1*16^33*G: */ + {{{0x13231e11, 0x1a1bf541, 0x3681e3e6, 0x123a1940, 0x0c36091f, 0x267fe466, 0x385d65ff, 0x3ec05dab, 0xe4f3}}, + {{0x2feb73bc, 0x08b0e15d, 0x151d1c98, 0x31f9d3b2, 0x02b7286c, 0x069b43a8, 0x34f1c166, 0x18ceb43b, 0x1e63}}}, + /* 3*16^33*G: */ + {{{0x2bf05bd6, 0x0e67c139, 0x12a99465, 0x3d5b80c8, 0x070deca2, 0x0bd47fad, 0x04fe9083, 0x0c906fb9, 0x900c}}, + {{0x300d358b, 0x394ab4ef, 0x04efb15d, 0x2614d60f, 0x0b2439d6, 0x31c8115c, 0x1f0f5f95, 0x3e7a3a2c, 0x6c31}}}, + /* 5*16^33*G: */ + {{{0x1f105c50, 0x29f0a332, 0x31385257, 0x3837bbde, 0x0233cd82, 0x2330d00f, 0x190aad62, 0x00d8aac1, 0x5a8d}}, + {{0x38a4cde9, 0x326c8060, 0x2d013c35, 0x017da299, 0x03ff74a6, 0x29adc905, 0x0e536936, 0x3aac44f5, 0xc059}}}, + /* 7*16^33*G: */ + {{{0x32d64feb, 0x11f862e6, 0x292292c6, 0x1cbe2964, 0x0ba4e837, 0x3ce95ddb, 0x2f60a48e, 0x1340c48c, 0xd93f}}, + {{0x34698359, 0x2c3ef564, 0x2c90da37, 0x3810c2fb, 0x1c8c4d93, 0x1cc47153, 0x32733a23, 0x15575172, 0x7925}}}, + /* 9*16^33*G: */ + {{{0x039fbc84, 0x08881335, 0x057a0167, 0x1c18a458, 0x2ac65b7e, 0x138af198, 0x328441b1, 0x1a71b8db, 0x2f07}}, + {{0x1c201bec, 0x3ee40b78, 0x04dd5d73, 0x29e6da93, 0x0e2149cc, 0x37c01e64, 0x3bdddfa5, 0x3cdc935c, 0xb434}}}, + /* 11*16^33*G: */ + {{{0x06a758ea, 0x14dfab32, 0x27f19c4d, 0x0620c624, 0x016e3991, 0x1a256855, 0x20309958, 0x19e01567, 0xfe7e}}, + {{0x1b7ab649, 0x13c8b657, 0x03120d1e, 0x2005c1d1, 0x09251f3b, 0x02385a61, 0x1dcb988c, 0x1a59e8a0, 0x38aa}}}, + /* 13*16^33*G: */ + {{{0x0cfffefa, 0x39c5589a, 0x0651afad, 0x060113dc, 0x03af8510, 0x3dbe4543, 0x03127d6d, 0x3d729d4e, 0x91ba}}, + {{0x1f7f6faf, 0x1f4dbcd3, 0x2fd303dc, 0x2fbcc439, 0x1d3d92f4, 0x25a7c49f, 0x3bcebe5d, 0x33c464d1, 0x04e5}}}, + /* 15*16^33*G: */ + {{{0x0d33c546, 0x3f0245fa, 0x05edaf32, 0x15d7ecca, 0x35ddd782, 0x314dcf83, 0x378a7cb2, 0x104872cf, 0x4458}}, + {{0x000b4fd4, 0x029b461c, 0x32ca7366, 0x0bc28f3e, 0x1ada2085, 0x097ab8e4, 0x0753a772, 0x24ddfcfe, 0x308d}}} + }, + { + /* 1*16^34*G: */ + {{{0x20eae29e, 0x1bedbab8, 0x14e1d071, 0x00d3cbc3, 0x1a4266c7, 0x1854de91, 0x3f331eb9, 0x3ea6c63a, 0x8c00}}, + {{0x2702414b, 0x1f4a9319, 0x1e36c54e, 0x3eb6bea0, 0x36c974c2, 0x30d0e8dc, 0x121a1a9d, 0x1c99ffa9, 0xefa4}}}, + /* 3*16^34*G: */ + {{{0x2bfd913d, 0x0fe5580f, 0x254c9eac, 0x29a039bb, 0x2a8d2050, 0x01e82130, 0x3ddf874d, 0x0aa9fa41, 0x3636}}, + {{0x052e243d, 0x113e6bab, 0x2b2faafc, 0x0c2ec435, 0x1a2a82d8, 0x18910dc3, 0x0afd5341, 0x1e19db2e, 0x48f2}}}, + /* 5*16^34*G: */ + {{{0x2d132896, 0x32aeafe6, 0x3bc6c967, 0x2c78eead, 0x19200dfc, 0x16b658b7, 0x21e02f29, 0x25db7cca, 0x4487}}, + {{0x2f685248, 0x23006c4a, 0x276aa7a4, 0x2d035698, 0x161a3306, 0x26a41dd1, 0x1afe1efc, 0x16183445, 0x27bd}}}, + /* 7*16^34*G: */ + {{{0x3fa2670c, 0x02055bda, 0x06273e6e, 0x003e0ae8, 0x35032474, 0x2a72aa0c, 0x383788b6, 0x0eb0a2f2, 0x4a4d}}, + {{0x16c1764d, 0x022e7ff7, 0x329beed8, 0x0c16532f, 0x302b9d49, 0x1dc4777b, 0x05a4f17e, 0x2e470061, 0x70ab}}}, + /* 9*16^34*G: */ + {{{0x0cb24aa7, 0x365abf89, 0x1345c530, 0x0c42318e, 0x38fe1890, 0x39bf627f, 0x11802c3a, 0x0b4642ba, 0x5f7b}}, + {{0x0a693d7d, 0x35e01d0d, 0x3c81d0c6, 0x237adc24, 0x267c47ce, 0x0fe028f3, 0x1f2b330a, 0x0d80313f, 0x0770}}}, + /* 11*16^34*G: */ + {{{0x2f7fb8bd, 0x0646f17c, 0x3e4090a4, 0x31192857, 0x0886d87b, 0x30939b65, 0x190d02ae, 0x1d144ce7, 0x5139}}, + {{0x03908c0f, 0x0252b0b6, 0x3f98d5a8, 0x3f0cb4f8, 0x015c47fa, 0x23fbf6ba, 0x03bf34b8, 0x050f91d9, 0xfcd7}}}, + /* 13*16^34*G: */ + {{{0x2e36ca73, 0x0add2457, 0x3bbf3ede, 0x321934da, 0x014887ea, 0x0a444afc, 0x3dfb8aa4, 0x05b58afe, 0xcf83}}, + {{0x2ec25534, 0x2d248650, 0x08d710f5, 0x25856636, 0x1cca681c, 0x11142243, 0x19d73e38, 0x2d637ad7, 0x09fe}}}, + /* 15*16^34*G: */ + {{{0x3752f97d, 0x3224df5a, 0x33476613, 0x0bbef1d7, 0x0fa6165a, 0x274a19a3, 0x3b49de53, 0x37a69312, 0x8610}}, + {{0x1f1b1af2, 0x015f7350, 0x05543e08, 0x2ad367d5, 0x33f99e57, 0x33666c94, 0x30bbc937, 0x25e80ad8, 0xd319}}} + }, + { + /* 1*16^35*G: */ + {{{0x20cb3e41, 0x25ff77f1, 0x08b92c09, 0x0f4213cc, 0x298ed314, 0x033b02a7, 0x0829f3e1, 0x1b39a775, 0xe7a2}}, + {{0x0f2cfd51, 0x3a2a5087, 0x20e83e20, 0x29acb010, 0x2fbb18d0, 0x2c01a86a, 0x3984b471, 0x238c03e9, 0x2a75}}}, + /* 3*16^35*G: */ + {{{0x3aee42db, 0x03e7f4af, 0x330714a7, 0x2eef16d1, 0x2cbfc1d9, 0x2dbb6e47, 0x19150fc7, 0x09f9f66d, 0xcc34}}, + {{0x15d87bdb, 0x188a7004, 0x272422dc, 0x3972eb63, 0x21520010, 0x38ff4fec, 0x1c6a1885, 0x26106948, 0xea24}}}, + /* 5*16^35*G: */ + {{{0x3ed4a086, 0x3d0d9b19, 0x29c410ef, 0x35d70563, 0x0b5cf4b1, 0x0f1617ef, 0x0445dec8, 0x016eb366, 0x948f}}, + {{0x1e2bca4b, 0x0a86003e, 0x03fa2d1a, 0x08ca29c7, 0x1139411c, 0x11429980, 0x22a3382f, 0x2a27fed6, 0x864c}}}, + /* 7*16^35*G: */ + {{{0x37542c21, 0x032fa9b2, 0x2a64c15c, 0x067d34a3, 0x1d6d43ae, 0x1bf11514, 0x19ac9065, 0x0658a4a4, 0x2584}}, + {{0x272bfabf, 0x2faf8c65, 0x0c2ad7b3, 0x38e861b9, 0x3513d5f3, 0x176a9331, 0x3244801e, 0x16c7c736, 0xfcb3}}}, + /* 9*16^35*G: */ + {{{0x0c1ecbf8, 0x0f1187d0, 0x2eed7ca4, 0x227c37a6, 0x28421f64, 0x25d53307, 0x3c52522a, 0x337104dc, 0x7e12}}, + {{0x30bed615, 0x3516e336, 0x3e1d9f59, 0x1a7d8763, 0x0d1259c9, 0x3e536af9, 0x1c837143, 0x13e22223, 0x7128}}}, + /* 11*16^35*G: */ + {{{0x14557d86, 0x1f999470, 0x2667ff41, 0x3fbb11e3, 0x05a6cf1c, 0x2e4729e8, 0x342a6772, 0x30bfca8d, 0x4b8e}}, + {{0x35167eb9, 0x3766c646, 0x3c3f692b, 0x357cbbc3, 0x27ac5f28, 0x101cb794, 0x157ab14a, 0x30ffc130, 0xfde6}}}, + /* 13*16^35*G: */ + {{{0x0780763c, 0x0ae0b4ed, 0x265691d5, 0x229b57a4, 0x3ac07e5f, 0x10db71a5, 0x23a42532, 0x3041cce5, 0xfcd5}}, + {{0x38e851cb, 0x1539d080, 0x16463a4b, 0x066c8b9c, 0x32e38cb1, 0x0836cd7d, 0x22c463b7, 0x2af8b954, 0x18dd}}}, + /* 15*16^35*G: */ + {{{0x1d8ef686, 0x338ef8c1, 0x2272e66b, 0x23923d00, 0x266e53f6, 0x22976be0, 0x3cbe5223, 0x0b3b9610, 0x900f}}, + {{0x2121a8cf, 0x1ce9259f, 0x09156d50, 0x1b37fd0f, 0x09d11059, 0x31546c4d, 0x0425ad61, 0x30557b18, 0x732a}}} + }, + { + /* 1*16^36*G: */ + {{{0x1e6b80ef, 0x33ca7acf, 0x179424f3, 0x32f2e59f, 0x3cbdc571, 0x1503088e, 0x22ec8d23, 0x2783b8d9, 0xb645}}, + {{0x1a71ba45, 0x0c2fc2d8, 0x0e35b2ff, 0x2ceb9b52, 0x261db3c4, 0x2b7c5b95, 0x3e06de1d, 0x21db41bc, 0x067c}}}, + /* 3*16^36*G: */ + {{{0x319888e9, 0x0e73c9e4, 0x2448a8b4, 0x04ae9afc, 0x2681673d, 0x1834c0a5, 0x3a6e2dde, 0x3a9dceb0, 0x1f90}}, + {{0x2f113b79, 0x1bf7f25f, 0x19522e65, 0x0dd47fb9, 0x2b96a821, 0x054f49c7, 0x2a10e958, 0x0d9f0576, 0x89be}}}, + /* 5*16^36*G: */ + {{{0x3562222c, 0x217bedbc, 0x1e6f2c60, 0x00d11e64, 0x0b52bade, 0x00aeb4cd, 0x3e0ad6e7, 0x39537b7f, 0x13a4}}, + {{0x28200145, 0x32c59a32, 0x1c904c08, 0x3e715deb, 0x209a52d4, 0x2b0be075, 0x2e813b2c, 0x1f539605, 0xc9d6}}}, + /* 7*16^36*G: */ + {{{0x343b46bb, 0x0df93703, 0x2c925254, 0x3b4e98fe, 0x055dbd12, 0x01f01761, 0x0aadd1d4, 0x07afc8cf, 0x6199}}, + {{0x0c20a848, 0x123d6407, 0x12ecd8ef, 0x2a1ca729, 0x3badf11c, 0x3ce1c59b, 0x1e492952, 0x38c23cff, 0x01c5}}}, + /* 9*16^36*G: */ + {{{0x121add3b, 0x396f8f77, 0x1727d8f7, 0x26a513d1, 0x1626118b, 0x0e736c34, 0x3d387490, 0x2ba92de1, 0xea27}}, + {{0x368ce7dd, 0x2d78a476, 0x24e1be71, 0x2c84b5a3, 0x1c2f6278, 0x0f3ac8c9, 0x217de572, 0x3c79b90a, 0xc70f}}}, + /* 11*16^36*G: */ + {{{0x211ff757, 0x3a2be2ed, 0x04c226e6, 0x133a5d07, 0x22b6da9b, 0x0043e2db, 0x3fd54ba9, 0x144d5adf, 0x5946}}, + {{0x094d031a, 0x2299bb2a, 0x3bffe3b2, 0x06ef1edf, 0x0406f996, 0x00e34057, 0x32750042, 0x0d833977, 0x3611}}}, + /* 13*16^36*G: */ + {{{0x236160b5, 0x1d89628d, 0x0e7ebc06, 0x314fc91c, 0x091ec0cc, 0x0ebde5c0, 0x33290e84, 0x1b8e457d, 0x16b2}}, + {{0x18a1dc0e, 0x11897efd, 0x0ba3ef81, 0x0d8eab1c, 0x3654d4e1, 0x190d4918, 0x2ef8bb63, 0x159698c0, 0x060f}}}, + /* 15*16^36*G: */ + {{{0x37b32db8, 0x25934a24, 0x247791f3, 0x07b5d27d, 0x2cea85c9, 0x2850f210, 0x19f931be, 0x14a57115, 0x024b}}, + {{0x2a64f760, 0x25153eaa, 0x05b81a95, 0x2ada0448, 0x1e5be862, 0x38a08731, 0x3309c7b6, 0x3be3d6ff, 0x609f}}} + }, + { + /* 1*16^37*G: */ + {{{0x096943e8, 0x3b683d6d, 0x273c5a5d, 0x1bc7f19f, 0x0f06231d, 0x08d2a846, 0x3b840793, 0x20320a02, 0xd68a}}, + {{0x2b133120, 0x25321099, 0x045295a2, 0x039ee3de, 0x30e28b5b, 0x2c7e45de, 0x186d00c4, 0x2a7ffd2d, 0xdb8b}}}, + /* 3*16^37*G: */ + {{{0x0ca1c4f9, 0x16d0aa86, 0x2b7e2823, 0x13bf8d32, 0x1f16f44f, 0x02e0f698, 0x1728c4c4, 0x3de3c8af, 0x7815}}, + {{0x3778bc15, 0x2ac7a8da, 0x177d1e19, 0x2d0b7985, 0x18c35d5c, 0x24f3cc51, 0x1af6a7dd, 0x007a334e, 0xc1c6}}}, + /* 5*16^37*G: */ + {{{0x2e8c8530, 0x349b870f, 0x38f4d8e6, 0x0b7da07b, 0x2a6c6d51, 0x1df19005, 0x040176e3, 0x1cf3683b, 0xc392}}, + {{0x398446c7, 0x100c3c3d, 0x2eed715c, 0x3b7f2f68, 0x03199850, 0x074e5107, 0x33c8e9d0, 0x2f9095d0, 0x8c41}}}, + /* 7*16^37*G: */ + {{{0x237a26c1, 0x07c902ec, 0x0dbf6a53, 0x1b1b9630, 0x103b2516, 0x0890c707, 0x011b0275, 0x1d11fd61, 0xda31}}, + {{0x2cf74d6f, 0x1460dbb3, 0x3a81525f, 0x1a0db175, 0x19d8b7d3, 0x21059f09, 0x18c69d23, 0x25ee1fd7, 0x753b}}}, + /* 9*16^37*G: */ + {{{0x3739dc49, 0x0ad8a2a4, 0x2f55603d, 0x24e4b699, 0x3f231a23, 0x12b1422f, 0x30e6c106, 0x39b2c0ab, 0x6a4b}}, + {{0x32edd5cf, 0x39a8ae77, 0x14a4a4d3, 0x1f8ad32c, 0x3a8058ab, 0x059b8d83, 0x107597dc, 0x23ea8aa2, 0xf15d}}}, + /* 11*16^37*G: */ + {{{0x06987fac, 0x22fa2831, 0x0a86f679, 0x3243e190, 0x098a3c8b, 0x260980fb, 0x27f1344e, 0x31a7c4eb, 0x01f7}}, + {{0x19174c68, 0x3e479ce0, 0x1f6bc263, 0x1fd77886, 0x1ab6f9cb, 0x040db8ca, 0x1a22de5b, 0x330fcdbf, 0x9d4e}}}, + /* 13*16^37*G: */ + {{{0x36daba4d, 0x34ce86f5, 0x03196261, 0x197ec388, 0x3a2bcb9c, 0x018bb763, 0x3d381cb7, 0x25005d87, 0x557e}}, + {{0x37a52316, 0x04dd286e, 0x243590a5, 0x3a6e3d7e, 0x0cbc86c5, 0x0d73e857, 0x3a7e046d, 0x23ce9807, 0x7a7e}}}, + /* 15*16^37*G: */ + {{{0x29f5341a, 0x0e3d4bfc, 0x29636b80, 0x31e8cb19, 0x3101419c, 0x27503a9e, 0x085a93b2, 0x36a08666, 0x3ada}}, + {{0x2586c6cc, 0x1456024d, 0x05e8fbcb, 0x35b4b96d, 0x2b1017e9, 0x38d6fcda, 0x1369f552, 0x0788a266, 0xbfea}}} + }, + { + /* 1*16^38*G: */ + {{{0x028d3d5d, 0x0256603f, 0x3449cea4, 0x04abae5c, 0x3a30b096, 0x3009c241, 0x0804252d, 0x3b5f7d97, 0x324a}}, + {{0x16ab7c84, 0x19c892be, 0x23328439, 0x084ec31f, 0x2c1f4f19, 0x03030d6b, 0x21f2ff13, 0x0d95dd2d, 0x648a}}}, + /* 3*16^38*G: */ + {{{0x2fd53ed3, 0x17245d60, 0x1a56ccef, 0x0fdd3ee7, 0x1f7c4916, 0x3d82e4c7, 0x372ad5b8, 0x02f56659, 0x2084}}, + {{0x1a7a7132, 0x1c50ff94, 0x0e708998, 0x21f11ce5, 0x3afac254, 0x2f51da9a, 0x18243487, 0x0d25f3b0, 0xf299}}}, + /* 5*16^38*G: */ + {{{0x08a35b35, 0x2f4b2ed6, 0x00a121ed, 0x2d762297, 0x08ebfd1a, 0x0f40a796, 0x339bbbd1, 0x2ffd83ac, 0xe6b6}}, + {{0x1c1007bd, 0x15ca4f6e, 0x3e999c7c, 0x0edb274e, 0x1961ddfe, 0x3d0f8e0d, 0x0d2f3266, 0x3caf4cc0, 0x1a5f}}}, + /* 7*16^38*G: */ + {{{0x00360dd3, 0x353be34b, 0x050e2090, 0x2a2a0db6, 0x0ce3bb47, 0x02e021b8, 0x099b288b, 0x05dd16f9, 0xe053}}, + {{0x3c24f87b, 0x0abb3644, 0x0103dc2b, 0x2e61f7a6, 0x36a01461, 0x02560ad6, 0x12f39cd8, 0x0edc6976, 0xdc1c}}}, + /* 9*16^38*G: */ + {{{0x1098dfea, 0x3051998b, 0x2a678797, 0x372cf24b, 0x3a5e57fa, 0x23974aa0, 0x06c59e01, 0x0ece9de2, 0xa815}}, + {{0x2e6d892f, 0x2926a77d, 0x2daf4158, 0x2d783dd0, 0x053e03b1, 0x236e715e, 0x060fc53d, 0x0e591874, 0x2a47}}}, + /* 11*16^38*G: */ + {{{0x0bcecfa5, 0x29f9de92, 0x316bb020, 0x0358b686, 0x0eda3b2a, 0x11a5718e, 0x0addadeb, 0x30ecc3fb, 0x4f05}}, + {{0x15d37b53, 0x3b34092a, 0x01b48cd2, 0x1fb90c7c, 0x1534b944, 0x18c8d856, 0x1426fadd, 0x267a980f, 0x53a4}}}, + /* 13*16^38*G: */ + {{{0x084b96aa, 0x1879d964, 0x22abcce4, 0x0a618d54, 0x3b980ed0, 0x101786a8, 0x3a91be26, 0x26ae67d9, 0xd930}}, + {{0x02b28a86, 0x09b13cdf, 0x3cfe978f, 0x2db27eeb, 0x34cb5fd3, 0x043c1989, 0x2c557d7e, 0x26caa6d3, 0x6ef9}}}, + /* 15*16^38*G: */ + {{{0x1f8fcf0e, 0x3dee3416, 0x3c4a6fac, 0x16dbff79, 0x2a3411d6, 0x30d11b7a, 0x22d35ba9, 0x1f284e15, 0x7d58}}, + {{0x18bc9459, 0x00706827, 0x323780a5, 0x18e402b4, 0x3d6ad0c4, 0x0d002db3, 0x04c61272, 0x1700e20c, 0xa729}}} + }, + { + /* 1*16^39*G: */ + {{{0x3d054c96, 0x3a2f4dcf, 0x0d1ca888, 0x31050eea, 0x3ee5dcee, 0x077f6f97, 0x1e61f6d5, 0x30524673, 0x4df9}}, + {{0x0ad10d5d, 0x0baeb01b, 0x28849019, 0x3541b370, 0x1d85d4b5, 0x25d308e8, 0x18728050, 0x3b14424b, 0x0035}}}, + /* 3*16^39*G: */ + {{{0x1def001d, 0x13c89769, 0x09ba27ef, 0x3e6ef5a6, 0x23b64b21, 0x02f47027, 0x22caf20e, 0x28cb6c9f, 0xa549}}, + {{0x30624783, 0x3576c69f, 0x2c9705ad, 0x05078a98, 0x259456eb, 0x330c3b62, 0x166cbdf4, 0x1e9e41b6, 0x799b}}}, + /* 5*16^39*G: */ + {{{0x052ed4cb, 0x16bbc797, 0x009ec5a0, 0x1537becf, 0x132e6ec9, 0x022f660d, 0x3ecd123f, 0x23cc3681, 0x7e79}}, + {{0x14bb9462, 0x15c5981e, 0x39f37a12, 0x1cd5c6ff, 0x32f057b1, 0x2a55277b, 0x1ac83041, 0x33312893, 0xd23d}}}, + /* 7*16^39*G: */ + {{{0x13630834, 0x37ce83ef, 0x3dac067f, 0x18fc4a18, 0x0c810884, 0x2e7a5aea, 0x14783ad5, 0x28800c54, 0x224f}}, + {{0x047a2272, 0x34f11cdf, 0x0a50f75c, 0x18a493b0, 0x1d09f53d, 0x2dc3e8e4, 0x2da5c3c4, 0x138caecf, 0xbbe5}}}, + /* 9*16^39*G: */ + {{{0x183c19d7, 0x19d92745, 0x02cf57bb, 0x2ed7916b, 0x228ef2bb, 0x28973390, 0x239e4129, 0x28331802, 0xc2d4}}, + {{0x0507928d, 0x0bca2e0b, 0x3345c977, 0x2012a0c5, 0x01260d26, 0x20ed7dfd, 0x06294d41, 0x283e7020, 0x65ad}}}, + /* 11*16^39*G: */ + {{{0x3c940c9a, 0x13202b52, 0x2f423308, 0x33cf384e, 0x0ddc2113, 0x161789d1, 0x1f3190e5, 0x0a9fb0c1, 0x2ec2}}, + {{0x051e7a4d, 0x34653f66, 0x1a35bdac, 0x101460f6, 0x1c7feb12, 0x3893d40a, 0x379684c2, 0x291a378c, 0x8b1d}}}, + /* 13*16^39*G: */ + {{{0x1d683eeb, 0x29c3b97f, 0x08d3133a, 0x0dbace28, 0x04b8f33e, 0x2bd94942, 0x28cecab1, 0x1a5ce3e6, 0xafc6}}, + {{0x30cd4509, 0x078a72ac, 0x1eddfdc9, 0x02ead549, 0x239c1657, 0x1671ff28, 0x22752bc3, 0x0865db74, 0x002c}}}, + /* 15*16^39*G: */ + {{{0x376f4293, 0x28807e1e, 0x13c5139e, 0x3a5e2d59, 0x0b282e10, 0x2f233cdc, 0x03309121, 0x1ed6a7cd, 0xd255}}, + {{0x1282740a, 0x36c61e89, 0x2405a5f1, 0x12da0e37, 0x0ad21fe3, 0x20bc1bad, 0x027f0126, 0x2cd0d579, 0xa787}}} + }, + { + /* 1*16^40*G: */ + {{{0x2c1f98cd, 0x2ff26722, 0x17f0308c, 0x0d224153, 0x06602152, 0x362a7073, 0x34870fae, 0x066a1291, 0x9c39}}, + {{0x14fc599d, 0x39f9780f, 0x064c8e6b, 0x14c9bddb, 0x20e64190, 0x3c112fc9, 0x1dd57584, 0x13c3d293, 0xddb8}}}, + /* 3*16^40*G: */ + {{{0x0fb64db3, 0x1ee6354e, 0x1dd53841, 0x3b79328e, 0x13b8d6a7, 0x2ee0fef9, 0x1ccb740b, 0x08e48a6f, 0xc114}}, + {{0x3c0259be, 0x08c33a7f, 0x14567d1e, 0x1d602413, 0x178bd1a8, 0x3b3793fa, 0x06fc2a5c, 0x3db716d2, 0x1237}}}, + /* 5*16^40*G: */ + {{{0x03081e46, 0x3b7b60d0, 0x14559ea1, 0x14886315, 0x2634713a, 0x3670b064, 0x37224082, 0x12fe0c69, 0x6c5b}}, + {{0x0bfbcd70, 0x347e72e0, 0x2c22a62e, 0x3433e09a, 0x2be47841, 0x11e18f38, 0x2d42fb23, 0x04dc5249, 0xcb05}}}, + /* 7*16^40*G: */ + {{{0x064dcd4b, 0x32b96bb1, 0x111c124d, 0x0c31f566, 0x310a450c, 0x1c19972a, 0x0ade4b56, 0x2a1599c3, 0xe1e9}}, + {{0x3b041f2c, 0x342d897a, 0x0a16b292, 0x113466ab, 0x2577927f, 0x310d666c, 0x1c531b7a, 0x02a55115, 0x562b}}}, + /* 9*16^40*G: */ + {{{0x2badd73c, 0x0161dbf8, 0x2a64b7d0, 0x36737640, 0x1c14208f, 0x29d390bb, 0x1b099778, 0x0695eb44, 0x51b2}}, + {{0x2b36d8d1, 0x3df52b87, 0x0c734ba6, 0x0804c3ca, 0x2c1cfa6c, 0x281fc074, 0x3d3e5d54, 0x0c040007, 0x0079}}}, + /* 11*16^40*G: */ + {{{0x3b09f34b, 0x35d742dc, 0x0cc66ce6, 0x221cf982, 0x339d61e5, 0x2d8a5bcf, 0x0b79861a, 0x3ce98ec7, 0x9701}}, + {{0x00df5793, 0x33721433, 0x3dcc794a, 0x012f0e5f, 0x16833771, 0x00c6d4c5, 0x30ed15d7, 0x12eee32b, 0x3dd4}}}, + /* 13*16^40*G: */ + {{{0x3f1e2f46, 0x1739888e, 0x32778301, 0x1c3dc7a1, 0x163c5752, 0x164b8103, 0x266cc445, 0x2d074b27, 0xa036}}, + {{0x1effb349, 0x1cc789a5, 0x3f0b1f4f, 0x2038a0b3, 0x1eb08d06, 0x07daa91e, 0x16b3d7df, 0x246800fa, 0xc3bf}}}, + /* 15*16^40*G: */ + {{{0x0c4cea08, 0x3362e40e, 0x20ea21db, 0x12d62e83, 0x00465265, 0x298454d0, 0x28c506f4, 0x3eb6ea93, 0x6a85}}, + {{0x1862f4f3, 0x0677b396, 0x3d721b6a, 0x09c692d0, 0x3e6230b4, 0x24cf0523, 0x0659d531, 0x11812eb9, 0x00b6}}} + }, + { + /* 1*16^41*G: */ + {{{0x20a959e5, 0x2884e084, 0x391d4cc5, 0x38524ea2, 0x0e06bb91, 0x017ca076, 0x12fdf8de, 0x05c2c774, 0x6057}}, + {{0x2385a2a8, 0x2266fa4c, 0x2e24c65e, 0x1454af0f, 0x1df26246, 0x268b6bdc, 0x24807add, 0x3c2c9a9a, 0x9a1a}}}, + /* 3*16^41*G: */ + {{{0x171c032b, 0x3536858a, 0x3afdc980, 0x1ad9a285, 0x0766c5ff, 0x046d7f7f, 0x002603dd, 0x2a3f35b8, 0x71eb}}, + {{0x1668359f, 0x1ead6a38, 0x34b4755e, 0x24c6b45d, 0x0cbb7f71, 0x18145bd5, 0x1d39def6, 0x049892d8, 0xd2ff}}}, + /* 5*16^41*G: */ + {{{0x2a03a61c, 0x01b91d14, 0x1070574d, 0x1e1a3d1a, 0x2a9dd050, 0x05d10aea, 0x09d232ca, 0x30c16cc9, 0x855e}}, + {{0x065dfc07, 0x37f1baab, 0x17e44965, 0x0cbdd3a8, 0x02fb4ed3, 0x0f2ffe6d, 0x01c17f54, 0x174bb17c, 0x0dd8}}}, + /* 7*16^41*G: */ + {{{0x1f32d706, 0x00302920, 0x06a0678b, 0x0633291d, 0x15bfa206, 0x034a68c2, 0x3fbf1f15, 0x121aaeac, 0x3ce4}}, + {{0x3c7fd9e4, 0x02dcd8df, 0x161e89f4, 0x345590f3, 0x094906ed, 0x3f411ac4, 0x3785288e, 0x10236ab8, 0xe775}}}, + /* 9*16^41*G: */ + {{{0x391cd3fb, 0x36d032ed, 0x329be686, 0x0a8cff65, 0x0844eb4a, 0x380c863e, 0x237faf02, 0x31450fd3, 0x11cc}}, + {{0x15160d86, 0x24dc5ae9, 0x0dd3472a, 0x02c7bf4b, 0x0cc239fa, 0x2389124e, 0x311deb52, 0x1acaa40a, 0x4aa5}}}, + /* 11*16^41*G: */ + {{{0x218f7552, 0x21ee4465, 0x0054fac3, 0x1044e2e6, 0x2382ddbd, 0x25ddd3e0, 0x09c6f43b, 0x2ec5f945, 0x0250}}, + {{0x3510b14d, 0x3c212588, 0x33d6f1e3, 0x001bcf0c, 0x29d817da, 0x35f7dd7f, 0x28082342, 0x0c3f26ef, 0x7319}}}, + /* 13*16^41*G: */ + {{{0x1f725d12, 0x1744fa4e, 0x0b5f4750, 0x1190aef7, 0x022fbfd9, 0x28e73828, 0x27fd3ab4, 0x27222cd1, 0x1a74}}, + {{0x23ac56e4, 0x04d94534, 0x190daa70, 0x1c821a62, 0x2f3d8f60, 0x22f9d70a, 0x00e2cf45, 0x34655cfb, 0x7e91}}}, + /* 15*16^41*G: */ + {{{0x29fae458, 0x18412394, 0x26ec97fd, 0x0297109d, 0x3b7b328b, 0x3455a977, 0x0218c109, 0x1a16f83e, 0xc750}}, + {{0x1757b598, 0x005a1065, 0x35951a2b, 0x1772940c, 0x32c7b40a, 0x0bd05319, 0x21e05fb5, 0x257e33e4, 0xead7}}} + }, + { + /* 1*16^42*G: */ + {{{0x2cb94266, 0x069a5cfb, 0x3d4df12b, 0x33bc3ee9, 0x0da31880, 0x10e69146, 0x08411421, 0x37e388e8, 0xa576}}, + {{0x21b28ec8, 0x3a2f846b, 0x114d9f3e, 0x0b8429fd, 0x0cd82c43, 0x2e5ebf96, 0x240b2c92, 0x2fc839d9, 0x40a6}}}, + /* 3*16^42*G: */ + {{{0x0d9ed6c1, 0x1a2bad63, 0x3d593d6b, 0x139d16f0, 0x1edd0ec2, 0x3f061dc1, 0x0f53e80b, 0x0cdb72dd, 0x0328}}, + {{0x38fafeee, 0x3b1baf9b, 0x1cb494ad, 0x16fd37c9, 0x0d7c8c26, 0x35650e88, 0x19f28c46, 0x260e04bf, 0x71a8}}}, + /* 5*16^42*G: */ + {{{0x3235983a, 0x066a6a34, 0x13bceb29, 0x22840dc0, 0x3e1531e3, 0x0e49b5c3, 0x11c54dc6, 0x13aba2e4, 0xce4f}}, + {{0x0d3cdecf, 0x33f5ac64, 0x2bf740ae, 0x1b1948a3, 0x30754352, 0x37809279, 0x0fbbb3ea, 0x3e5cf0e4, 0xf3c9}}}, + /* 7*16^42*G: */ + {{{0x15b0e6c9, 0x1b6aad99, 0x06e4c89a, 0x17fe73de, 0x38bcbddb, 0x0a3ecdb7, 0x0622278e, 0x2fe952e6, 0x4dbe}}, + {{0x1eb2cc25, 0x2529e155, 0x0504efae, 0x24c46caf, 0x2229f358, 0x2989b9b8, 0x13aedf45, 0x39ec0f24, 0x10fe}}}, + /* 9*16^42*G: */ + {{{0x25857295, 0x13806846, 0x3433f016, 0x32391fc0, 0x1ca12069, 0x38463f28, 0x05c218b2, 0x0902ffbd, 0xa42a}}, + {{0x0a7eb9c1, 0x1acddffb, 0x15193955, 0x28708b34, 0x1da4c427, 0x1ac8ac93, 0x05d4567a, 0x2cfc9840, 0x3aa0}}}, + /* 11*16^42*G: */ + {{{0x2fcdc098, 0x0883fd55, 0x2e468032, 0x02b803da, 0x0499c155, 0x3c7e1b03, 0x322267a7, 0x0acbe5be, 0x34e1}}, + {{0x2a7474e2, 0x132c6b79, 0x19883f66, 0x37d44c3c, 0x3972db04, 0x132f2105, 0x1d322d97, 0x30b775ed, 0xa64a}}}, + /* 13*16^42*G: */ + {{{0x0f173b92, 0x335bad7a, 0x29fb7611, 0x1f9cbd05, 0x0d65683b, 0x0c68863d, 0x391f29be, 0x3490366e, 0x10f4}}, + {{0x233146c2, 0x240801b5, 0x086adb7c, 0x2edda745, 0x3908ba90, 0x2c96968c, 0x353ad211, 0x0b654245, 0x850e}}}, + /* 15*16^42*G: */ + {{{0x28d84958, 0x39bf4766, 0x0acc5cae, 0x0477ac5b, 0x00cc866a, 0x066e5db5, 0x277e749f, 0x3a02da6d, 0xe846}}, + {{0x3882cf9f, 0x031191ed, 0x1e0c1a64, 0x1468cd9c, 0x18b76fad, 0x2f64411e, 0x07e2541d, 0x2e3f2253, 0xa29c}}} + }, + { + /* 1*16^43*G: */ + {{{0x3e58ad71, 0x3dd8e226, 0x39a3a208, 0x0c347d73, 0x1e8c38bb, 0x17fa58a7, 0x2c3e30a0, 0x29e30a37, 0x7778}}, + {{0x3d9f43ac, 0x2d44ff07, 0x324ac563, 0x2ce1047f, 0x3f580087, 0x26384bcb, 0x1b22ff70, 0x1b66ad69, 0x3462}}}, + /* 3*16^43*G: */ + {{{0x3319c869, 0x3df1bab8, 0x21eb2702, 0x2a7e575d, 0x0cacdc18, 0x20e408bf, 0x33fc8d01, 0x01176605, 0x3018}}, + {{0x12b856f0, 0x3031db27, 0x23d9a7bf, 0x0aa13292, 0x222e3bca, 0x1890c835, 0x3b7b6f86, 0x315e0940, 0xac5f}}}, + /* 5*16^43*G: */ + {{{0x25ed29b5, 0x319a61be, 0x12add1b4, 0x20c2d81c, 0x23c885f5, 0x2d9f6e69, 0x17ef343a, 0x206d87b9, 0x3228}}, + {{0x3cd15ad2, 0x3d3c49b9, 0x0ee7604e, 0x20ebaae5, 0x1531e1ca, 0x02c677d0, 0x0344eb11, 0x00a105e8, 0x1677}}}, + /* 7*16^43*G: */ + {{{0x06c96100, 0x2fea101e, 0x2e9c8e63, 0x18c046a9, 0x33dbcca1, 0x0f766cb7, 0x31b9ffb4, 0x11ceb03e, 0x3f38}}, + {{0x32624707, 0x078ab06f, 0x375f1bcf, 0x15c71f02, 0x079ce566, 0x131118bc, 0x00395253, 0x27157d75, 0x70c6}}}, + /* 9*16^43*G: */ + {{{0x3d22d2ac, 0x0d31bb1b, 0x1caace02, 0x377f849b, 0x05df2f10, 0x0f03825e, 0x3a76dcb4, 0x04f17f49, 0x2881}}, + {{0x0f42a268, 0x207ad57e, 0x148c8fd0, 0x30f51285, 0x176137dd, 0x1ddc9832, 0x3c5c8f20, 0x3ac0563e, 0xa1a7}}}, + /* 11*16^43*G: */ + {{{0x245f8ea8, 0x12ea0374, 0x24d2900d, 0x1c9238e5, 0x119fe5d1, 0x3d36575c, 0x23a2a553, 0x28803211, 0xf963}}, + {{0x19bc99eb, 0x2f157ec1, 0x18b60824, 0x2e3c8d67, 0x3427208b, 0x1c88c07f, 0x383c0a3b, 0x2509a31f, 0x9c85}}}, + /* 13*16^43*G: */ + {{{0x2606a315, 0x386a20c4, 0x26963ad9, 0x1c981cbc, 0x0e097e40, 0x362ca964, 0x0d9a7f98, 0x08933fdc, 0xa5d9}}, + {{0x1e3b68d1, 0x0d584cd6, 0x111a7c9d, 0x13434d1f, 0x180de9ed, 0x0c1aaf5e, 0x0da5b343, 0x22c00ec8, 0x8732}}}, + /* 15*16^43*G: */ + {{{0x06231493, 0x336ded50, 0x0cc4d469, 0x1046a0c3, 0x25e6a496, 0x13907403, 0x3c3604eb, 0x260b86dc, 0xf1fe}}, + {{0x358848c1, 0x25aa6699, 0x25ff0d01, 0x1cfecd1b, 0x3d99d3f1, 0x34f0817d, 0x24ddc216, 0x067abb66, 0x2e20}}} + }, + { + /* 1*16^44*G: */ + {{{0x06d903ac, 0x027b6a70, 0x1ad7e5cb, 0x3e589d39, 0x3afd2ed5, 0x0a7f4c39, 0x3a844637, 0x2557b98d, 0x0928}}, + {{0x1bcd091f, 0x14603a4d, 0x0a8d83fc, 0x0f49bbea, 0x3a95eeac, 0x1e284c24, 0x342a827b, 0x08400f4f, 0xc256}}}, + /* 3*16^44*G: */ + {{{0x3874b839, 0x0444a1d5, 0x13d2b418, 0x10456ce5, 0x30b6aebe, 0x37c37ec8, 0x1e5a8053, 0x2e07f038, 0x3e03}}, + {{0x3c0594ba, 0x03073959, 0x1ab5b8da, 0x39717c3f, 0x198f667d, 0x3d981d5c, 0x07f42c44, 0x3858f7fc, 0xd13a}}}, + /* 5*16^44*G: */ + {{{0x0357a513, 0x28fde39a, 0x1b3023f3, 0x146f44d1, 0x2922c5f1, 0x3e8a0ea8, 0x0492cd62, 0x302de8bd, 0xe662}}, + {{0x2017d07e, 0x24a88072, 0x1538d891, 0x00d73589, 0x21a419d8, 0x2b882284, 0x2452305d, 0x064f3984, 0xab0b}}}, + /* 7*16^44*G: */ + {{{0x1f37d242, 0x2657dfbf, 0x39c14b04, 0x27fb2981, 0x23587dc2, 0x218b1f2f, 0x0f6cb843, 0x202c7253, 0x40bf}}, + {{0x26405088, 0x347609e6, 0x2bd35583, 0x0c87ae90, 0x26fe1274, 0x0ffa6c6c, 0x2aaf04f5, 0x374d7615, 0xb579}}}, + /* 9*16^44*G: */ + {{{0x195a3558, 0x2bcacd91, 0x234a7f2b, 0x01c7e178, 0x1b59f6ac, 0x3e5e04e3, 0x1ca70806, 0x3fa5d807, 0x3d14}}, + {{0x2443df4c, 0x1ab6ceb1, 0x3c1d727c, 0x3828b851, 0x356e1482, 0x26a4c76f, 0x281ef8f2, 0x2f75ba11, 0x16c6}}}, + /* 11*16^44*G: */ + {{{0x02b1fc24, 0x37a7d6b6, 0x23f7570e, 0x0a36071f, 0x12486525, 0x06b134b2, 0x265251cc, 0x29503a0b, 0xdd6f}}, + {{0x0e9b74ca, 0x290c7118, 0x17322304, 0x04379afb, 0x257e77ec, 0x1bc7afc5, 0x3186fe36, 0x0adfac74, 0x67e6}}}, + /* 13*16^44*G: */ + {{{0x3dd08e02, 0x07aa4564, 0x1adf0288, 0x2151edff, 0x3d1e8010, 0x1a5266a8, 0x15d780f8, 0x0b6a0b79, 0x13fa}}, + {{0x3cb03410, 0x29550770, 0x1a42b97d, 0x112beec6, 0x3432c7e6, 0x0d5881ae, 0x1da72313, 0x0e2c1155, 0x1363}}}, + /* 15*16^44*G: */ + {{{0x144ee41a, 0x308ceae6, 0x37d69a6a, 0x26d5b74e, 0x06828287, 0x3042d9cb, 0x30a443f7, 0x121474f1, 0xd06c}}, + {{0x0b295e6f, 0x3c7e13a6, 0x162ee252, 0x1ee10d18, 0x3630919b, 0x02b353d3, 0x0d0adbbb, 0x3f530161, 0x5815}}} + }, + { + /* 1*16^45*G: */ + {{{0x23d82751, 0x1eab9d45, 0x3ad35452, 0x116d2a41, 0x23b28556, 0x0193ce83, 0x1b109399, 0x3fbcfb1b, 0x85d0}}, + {{0x0eb1f962, 0x0b08de89, 0x07733158, 0x21d47a5a, 0x2cf5663e, 0x3525b960, 0x38c0be29, 0x192104e8, 0x1f03}}}, + /* 3*16^45*G: */ + {{{0x2cde4cf3, 0x26554187, 0x38a066ab, 0x10394d51, 0x1d9ae793, 0x30b49b45, 0x022c3be7, 0x2ad2b045, 0x384d}}, + {{0x252d0566, 0x1f1e5ac8, 0x351ba73b, 0x10c28ce5, 0x34c6f01f, 0x13b5b68a, 0x1ca43bfb, 0x316f346e, 0xd6e3}}}, + /* 5*16^45*G: */ + {{{0x1e5238c2, 0x22bcfa48, 0x00ecb8b9, 0x0d57d70e, 0x02ed4840, 0x05842d3a, 0x015aa41b, 0x3b03adf5, 0x14f0}}, + {{0x12f07922, 0x3a1a8d1e, 0x304939d6, 0x17003600, 0x02747fd2, 0x3f1cf8e1, 0x35d80921, 0x354f7520, 0xab12}}}, + /* 7*16^45*G: */ + {{{0x1543e94d, 0x3d8d4bbf, 0x2f98e188, 0x04c0a9d5, 0x1a0ddadd, 0x30d19e29, 0x0287ec41, 0x3ceede0b, 0xeb42}}, + {{0x05924d89, 0x01567791, 0x20d6d424, 0x3611a379, 0x0dfb774c, 0x03755cbf, 0x1d92dc9a, 0x1b41d3c9, 0x234a}}}, + /* 9*16^45*G: */ + {{{0x3e19aaed, 0x0c9396d5, 0x06673270, 0x26eb37a3, 0x06a92045, 0x3b00bdb8, 0x020d9a9e, 0x0e32945a, 0x1cf1}}, + {{0x292f400e, 0x04dba975, 0x3c77ffbc, 0x27bbe3fb, 0x2dde1747, 0x0dca99ad, 0x063865f4, 0x36bcc5c7, 0xd6ff}}}, + /* 11*16^45*G: */ + {{{0x36a8aa39, 0x3db03a7e, 0x278fac55, 0x2998ded2, 0x1990d937, 0x16825a12, 0x0d412c87, 0x21af97d0, 0xb586}}, + {{0x2b493c1f, 0x3f1e4d74, 0x2db347b8, 0x2f6be639, 0x00a91dab, 0x11e35153, 0x38c2c149, 0x3550c931, 0x5632}}}, + /* 13*16^45*G: */ + {{{0x303b4cc5, 0x3a47af8e, 0x21c77c2e, 0x0a0c6e96, 0x33a80257, 0x16f13f9f, 0x3cc2b67b, 0x276c1ae2, 0x5fc1}}, + {{0x25b57c28, 0x0ece7ee1, 0x0087ec4a, 0x1dbd40f3, 0x3a5ef492, 0x084e3e68, 0x0c7c66ee, 0x21303b26, 0xec8e}}}, + /* 15*16^45*G: */ + {{{0x0cb38cb5, 0x2d2e15f5, 0x1388948b, 0x02dff7d3, 0x3eea1be1, 0x2a2903f4, 0x1e289deb, 0x2dc350bb, 0xb88f}}, + {{0x1965f3d7, 0x1efe9d59, 0x3af8c719, 0x13cf8489, 0x35a8e24d, 0x12ee652c, 0x23280603, 0x0dab51ba, 0xd6c7}}} + }, + { + /* 1*16^46*G: */ + {{{0x0526087e, 0x3d501209, 0x2da20308, 0x3edb6220, 0x18b85dfd, 0x26d8105e, 0x2ce97c1c, 0x0373a5fb, 0xff2b}}, + {{0x30c29907, 0x32547807, 0x10e2ceb2, 0x2dfb5bee, 0x107936c7, 0x13137153, 0x0ba188af, 0x04ffbd49, 0x493d}}}, + /* 3*16^46*G: */ + {{{0x39d681f9, 0x164153f9, 0x08feb9fc, 0x3383bbeb, 0x2c94b066, 0x1ffc9780, 0x3230888b, 0x3f7c9dd7, 0xc745}}, + {{0x3bbb1247, 0x00c5cd0d, 0x27d45c76, 0x36f4cd71, 0x2818678c, 0x04e531c3, 0x1e5e78a7, 0x08bcbdae, 0x5902}}}, + /* 5*16^46*G: */ + {{{0x35cd0ea3, 0x38133bb4, 0x0cac4815, 0x111e3a08, 0x32e7f2b3, 0x16797ad9, 0x1050b27a, 0x1e7cea5d, 0xabb2}}, + {{0x3c307bce, 0x1c24c4cd, 0x202f3b64, 0x25da4167, 0x078ed47c, 0x12f8300c, 0x3970d9fb, 0x040eefc5, 0x5dee}}}, + /* 7*16^46*G: */ + {{{0x1bc9ee3e, 0x30b8bcfc, 0x3e7382c5, 0x27e86a58, 0x27ed11ea, 0x2baa9d09, 0x0682827f, 0x0542d67f, 0x3f81}}, + {{0x199aae06, 0x33ab6c31, 0x0da81603, 0x08ecb73f, 0x39566276, 0x06facf11, 0x3a82d467, 0x229a3f6f, 0x19c8}}}, + /* 9*16^46*G: */ + {{{0x38e4a007, 0x05c6fbeb, 0x0bb358b6, 0x3b3bb3c2, 0x16c7ec15, 0x12e8cea9, 0x02de6959, 0x04cb7402, 0x5cf8}}, + {{0x1068b883, 0x398fc242, 0x39c7fe8c, 0x251be5b1, 0x0c3df6c8, 0x35056212, 0x1fa0df4a, 0x3b970358, 0xb45a}}}, + /* 11*16^46*G: */ + {{{0x26c2d4a7, 0x255bf9ec, 0x3cfffb10, 0x30dbe4ce, 0x004ed21b, 0x38ce5cf1, 0x3a494653, 0x3f934352, 0xb6d5}}, + {{0x3ae86371, 0x063739f8, 0x35e3cc81, 0x16df939b, 0x3ffd8e74, 0x33e48277, 0x3d6c14df, 0x1ce84eae, 0x47f3}}}, + /* 13*16^46*G: */ + {{{0x3c66dd33, 0x024cd88b, 0x1dc76dc5, 0x23ef23fc, 0x29b022ea, 0x2c6c5400, 0x3588706b, 0x2ef019b3, 0x61c8}}, + {{0x36f10bfa, 0x0eeea7ce, 0x2820c8ca, 0x1441bab0, 0x05d3fb6a, 0x1a6652e6, 0x0f703446, 0x2788e795, 0x9359}}}, + /* 15*16^46*G: */ + {{{0x1d6b2ff8, 0x2016df33, 0x286c8fa9, 0x18cdb05c, 0x03bdf187, 0x27d4dcfb, 0x2785187c, 0x0ae95d09, 0x94e3}}, + {{0x2ce1af3e, 0x37521554, 0x26bfe13a, 0x0ebc1094, 0x2d9e8cb3, 0x07922198, 0x204e192f, 0x1122d0f6, 0x0d1b}}} + }, + { + /* 1*16^47*G: */ + {{{0x3856e241, 0x203978b3, 0x0d6dd287, 0x3c7b8523, 0x1b212b57, 0x0acb98c0, 0x080ea9ed, 0x2ef92c7a, 0x827f}}, + {{0x2ec293ec, 0x1816da2e, 0x2903166d, 0x3de98c61, 0x1d12687f, 0x3bcb19f4, 0x27b0b71b, 0x27248f1c, 0xc60f}}}, + /* 3*16^47*G: */ + {{{0x3bb80fa7, 0x0d12172c, 0x30413886, 0x29f69aed, 0x20819f3a, 0x0681af4c, 0x0c2fbc0d, 0x38c7d8c2, 0x0857}}, + {{0x09366b2d, 0x3660847c, 0x0d7016ab, 0x0b8dc10f, 0x0b714717, 0x1f327477, 0x0172092d, 0x24d08eb8, 0xf643}}}, + /* 5*16^47*G: */ + {{{0x09c70e63, 0x1740b0e8, 0x353d496f, 0x2ee2de39, 0x0a672e9c, 0x171955d9, 0x16004354, 0x333a95af, 0x28aa}}, + {{0x3057da4e, 0x27c0e20b, 0x04da1e8b, 0x3f167391, 0x28ebb7f5, 0x22599f1d, 0x20e1567a, 0x0c8bbe06, 0x2b69}}}, + /* 7*16^47*G: */ + {{{0x33e674b5, 0x007714bd, 0x3060aac6, 0x363da739, 0x2b8a4f92, 0x36cb26f3, 0x1a66145d, 0x2d896815, 0xa2f3}}, + {{0x0e937941, 0x024e3238, 0x033fa53b, 0x08be8c5f, 0x2a7c4b92, 0x112a43cc, 0x068ae800, 0x28565853, 0x620e}}}, + /* 9*16^47*G: */ + {{{0x191eb056, 0x1d8058c7, 0x2cfd386c, 0x00bbf6e3, 0x3515f5a0, 0x22d71a8f, 0x259231d9, 0x20f27aab, 0x3c4f}}, + {{0x205cecab, 0x109624f6, 0x1cf6b877, 0x20ad5120, 0x32788019, 0x3595cf0e, 0x28b6a33a, 0x2401d452, 0x9447}}}, + /* 11*16^47*G: */ + {{{0x3d86dfa9, 0x24187f6e, 0x1b993a71, 0x0e2d2902, 0x103baadc, 0x30780fa0, 0x167d4e29, 0x384a22a6, 0xaff8}}, + {{0x01d12681, 0x1c40f0db, 0x019f9c70, 0x045b6a51, 0x0f53f4f9, 0x0faea87f, 0x37c3fd3d, 0x12ecc84d, 0x8d8b}}}, + /* 13*16^47*G: */ + {{{0x189ba9c1, 0x23c9cdae, 0x09d338e2, 0x03df2968, 0x0ee579e4, 0x16098abb, 0x000b3e84, 0x1e114a37, 0xd3fb}}, + {{0x2b51b267, 0x186e237f, 0x011ade00, 0x073b7570, 0x370fe634, 0x32815d62, 0x2b4e7ca7, 0x350d3be9, 0xf894}}}, + /* 15*16^47*G: */ + {{{0x0f2bb909, 0x36a5b074, 0x3598d999, 0x24409f14, 0x187d7f63, 0x1ca620e4, 0x1aa88ff4, 0x0c0382b2, 0x4ec9}}, + {{0x24cf4071, 0x2228e0fe, 0x1ac3827b, 0x0b85a083, 0x0c49bad5, 0x03711461, 0x304dc5c8, 0x2841af86, 0x782b}}} + }, + { + /* 1*16^48*G: */ + {{{0x2120e2b3, 0x3ced63e8, 0x347f9aa7, 0x163f739f, 0x26e5217a, 0x392b8d33, 0x1bdbae7b, 0x127c87d4, 0xeaa6}}, + {{0x3a5ad93d, 0x11e94c16, 0x13f7e59d, 0x29ae597c, 0x39aa5a01, 0x2a03e261, 0x3b03ac69, 0x1e7b56ee, 0xbe32}}}, + /* 3*16^48*G: */ + {{{0x3f2e070d, 0x160ff4e8, 0x12a6a98f, 0x2aadc731, 0x1047e229, 0x1cc70ee1, 0x34abff48, 0x297a410b, 0x4b72}}, + {{0x296dd780, 0x112ea0bb, 0x2948c3de, 0x2d197774, 0x0f3c10b0, 0x1deecdb4, 0x2e1cf602, 0x0753875a, 0x599e}}}, + /* 5*16^48*G: */ + {{{0x0a02591c, 0x2739ff61, 0x05125a1e, 0x3d526596, 0x21fd613e, 0x1afefad7, 0x1c8e285a, 0x24ff194e, 0xa9fc}}, + {{0x29bec2dc, 0x242b77bd, 0x3cf72537, 0x22231057, 0x1165e5ca, 0x1305e86a, 0x387173e8, 0x39ce7714, 0x9c2c}}}, + /* 7*16^48*G: */ + {{{0x2d968b59, 0x0401b838, 0x3cbbc2e1, 0x28a2eb84, 0x1b027709, 0x35eb0482, 0x39f0a6a7, 0x005f069b, 0xc940}}, + {{0x0de572fb, 0x3bf5d902, 0x390c9c8f, 0x210b2d90, 0x35742ce2, 0x2286fe96, 0x3862013b, 0x08940326, 0x39d9}}}, + /* 9*16^48*G: */ + {{{0x326b3332, 0x0a1cccd5, 0x3ee5de6a, 0x00e2341c, 0x0bf8e031, 0x1e4e97dc, 0x10024ec6, 0x2ee75fbb, 0x1f84}}, + {{0x14e8d52e, 0x1510a28c, 0x36dc3a25, 0x2f338b50, 0x39edf0c2, 0x1f09fdd6, 0x29ecc254, 0x1b41caf2, 0xee72}}}, + /* 11*16^48*G: */ + {{{0x0defa98e, 0x336a952b, 0x1ac27995, 0x12111a04, 0x11e9c772, 0x2055ece6, 0x1fcd06ca, 0x38224251, 0x0f13}}, + {{0x3e286767, 0x0229dda6, 0x2ceaccdc, 0x1f9c1785, 0x3362db28, 0x0fe2c29e, 0x27c5035e, 0x087c5d93, 0xadd5}}}, + /* 13*16^48*G: */ + {{{0x29f59b6b, 0x178700ef, 0x1888e2fa, 0x2ce318f0, 0x1826d3e9, 0x0a2874b5, 0x1ec7db37, 0x24695477, 0xdde1}}, + {{0x26cb1410, 0x1ab658a4, 0x3154fecf, 0x15ce2ef9, 0x12e14e8b, 0x1d5f5871, 0x275cbe0a, 0x3ede00a0, 0x5b2b}}}, + /* 15*16^48*G: */ + {{{0x09c6b699, 0x1a3157f7, 0x3e46871b, 0x1bd5cd5a, 0x341682a8, 0x1b5efe5e, 0x36f7a5a1, 0x004bbb60, 0x5fab}}, + {{0x01c6c3aa, 0x05cc854b, 0x2883519b, 0x2ac45ffa, 0x162f7b90, 0x2ed044c3, 0x3d144e9e, 0x3e9c28f0, 0x2d9b}}} + }, + { + /* 1*16^49*G: */ + {{{0x1a34d24f, 0x388d8cb7, 0x1a137401, 0x2db63c32, 0x342ee541, 0x077db7b3, 0x3169d939, 0x0b50f173, 0xe4a4}}, + {{0x1eba9414, 0x29fdc4c7, 0x0d8e4f13, 0x21bbb7ea, 0x0ad34ce8, 0x326733ee, 0x1c73526f, 0x24b9c5b4, 0x4d9f}}}, + /* 3*16^49*G: */ + {{{0x3bea0c68, 0x321042bc, 0x37b392b5, 0x10c048d9, 0x396faf09, 0x26f23a34, 0x2a3a2494, 0x258d3855, 0x3e41}}, + {{0x1a45edb6, 0x32edbfdc, 0x03cda1ab, 0x2846518c, 0x0693062f, 0x0f2ff8dc, 0x321f7f37, 0x31676492, 0x0123}}}, + /* 5*16^49*G: */ + {{{0x139824d7, 0x3dd748f2, 0x11c9897a, 0x2ded930d, 0x3f0b576e, 0x128f98bd, 0x17508eed, 0x0e3d5157, 0x8d94}}, + {{0x1366489f, 0x28013d22, 0x26b063d8, 0x2e78ae0c, 0x36ef6f8f, 0x182f4c6a, 0x26c2a2ca, 0x381cd3fb, 0x3261}}}, + /* 7*16^49*G: */ + {{{0x18d713de, 0x39201c6a, 0x028e6208, 0x1830bedd, 0x25454393, 0x2a44a8bf, 0x254420d4, 0x0931563b, 0xb725}}, + {{0x1b8350e9, 0x1bff9496, 0x04a5fcb7, 0x20b49bf9, 0x16941504, 0x0b460ba7, 0x03e45104, 0x2ce6a28a, 0x4c51}}}, + /* 9*16^49*G: */ + {{{0x3e3b2cb4, 0x331b0a4f, 0x37210402, 0x127cd6fc, 0x21149e30, 0x31db8e04, 0x112519ad, 0x17d6885b, 0x3de4}}, + {{0x307eb02f, 0x1878ceb0, 0x287044cf, 0x0f8a3996, 0x3c910682, 0x022a92a5, 0x2addc50e, 0x21661017, 0xba2a}}}, + /* 11*16^49*G: */ + {{{0x2ce4e5bf, 0x08d1d9bd, 0x09005b17, 0x19f2a1a8, 0x0906ae9b, 0x0ff38dd2, 0x1be87c1e, 0x3c71a256, 0x8511}}, + {{0x01789c08, 0x3f24a513, 0x05365262, 0x2a1e226f, 0x2a00232d, 0x377dfb1a, 0x0d4874c1, 0x3d73e46f, 0xecdf}}}, + /* 13*16^49*G: */ + {{{0x3d3258ab, 0x06d59a28, 0x2bc14dc3, 0x3490a062, 0x14ab5957, 0x2871cbb8, 0x360222cf, 0x014ba073, 0x8c5a}}, + {{0x022d0f8f, 0x15f8214c, 0x0d944ade, 0x36ba3e70, 0x0c08c246, 0x2a031e41, 0x3bda1079, 0x36d2ed10, 0x6811}}}, + /* 15*16^49*G: */ + {{{0x3f91bcee, 0x1630a82a, 0x20c0d841, 0x33c763c7, 0x2bf137f5, 0x18f3b155, 0x13560bdc, 0x3e05b7af, 0xcef7}}, + {{0x01966b33, 0x2ed36a7e, 0x172f6ac6, 0x0f92c0a8, 0x1d245fa6, 0x0ecce700, 0x08701246, 0x1320d8dd, 0x67e7}}} + }, + { + /* 1*16^50*G: */ + {{{0x0300bf19, 0x1c5cee75, 0x08fea494, 0x2d4d5daa, 0x352b6b92, 0x183eb6ac, 0x0bdd9541, 0x03fbcd83, 0x1ec8}}, + {{0x0107cefd, 0x1c737073, 0x295a07b6, 0x11b9dfd8, 0x2bbf5e01, 0x2925629e, 0x1340d2f3, 0x3a4dd5ad, 0xaeef}}}, + /* 3*16^50*G: */ + {{{0x12fea1f9, 0x2c5f2ef1, 0x00452b94, 0x3fc2d423, 0x106531c4, 0x3f76ad9c, 0x1f2e83bc, 0x22029574, 0xa6dc}}, + {{0x3bc345e9, 0x2c705391, 0x268f7e63, 0x1ee276df, 0x2cbc5005, 0x1a0e845a, 0x367c3038, 0x2a151f70, 0x7ef1}}}, + /* 5*16^50*G: */ + {{{0x06d6c9b3, 0x235030fc, 0x0865637c, 0x1b133a1d, 0x2481ba8c, 0x308a71e2, 0x245992bd, 0x2a4ffa90, 0xfe6b}}, + {{0x2948bdfb, 0x30b1e23e, 0x1c2e9b00, 0x203c6fc1, 0x013b56d9, 0x2d06cd15, 0x39872b6b, 0x0635d014, 0x7ee9}}}, + /* 7*16^50*G: */ + {{{0x0cf95151, 0x08bc41cc, 0x02c4b644, 0x19201b91, 0x08ded1b9, 0x03230b70, 0x098bfb02, 0x38bc51bf, 0x15d5}}, + {{0x2ff8ecf2, 0x20a81f30, 0x1d8c0f94, 0x0813ee5f, 0x1023f9bb, 0x038425e2, 0x3d4ec7f9, 0x0b8c6457, 0xa5b7}}}, + /* 9*16^50*G: */ + {{{0x296a5658, 0x35e042e4, 0x1ef65643, 0x052c9490, 0x2e29be38, 0x1f80249e, 0x0447ad8c, 0x3a1c95a2, 0x84c0}}, + {{0x181b80d1, 0x3659ca6f, 0x34f1fd22, 0x2986a607, 0x13725ed3, 0x1f8c6419, 0x022c4a08, 0x20e03058, 0x2659}}}, + /* 11*16^50*G: */ + {{{0x14dc6a0f, 0x1d6ed722, 0x2fe15753, 0x10d06450, 0x0077c274, 0x09939e8b, 0x3731d565, 0x2c71c6a4, 0xfed6}}, + {{0x176fc7e0, 0x32e35cb6, 0x23fc409c, 0x1d3564c2, 0x13ae2313, 0x24606b93, 0x3ff0a847, 0x2af9ac3f, 0x8de2}}}, + /* 13*16^50*G: */ + {{{0x18e29355, 0x2ce217c4, 0x1720d86d, 0x0723a4ce, 0x23b9d82f, 0x3be18100, 0x3cbc70fc, 0x137664b4, 0x2a6a}}, + {{0x35cc2872, 0x014f803e, 0x0c4c76c0, 0x24168e99, 0x28f90dfe, 0x3f720789, 0x27e0c760, 0x37ee9f12, 0x8677}}}, + /* 15*16^50*G: */ + {{{0x2148dabf, 0x3e7ea23f, 0x09d78eb1, 0x2b74ae4d, 0x3ae735c1, 0x193b08d7, 0x27546d97, 0x24c09b24, 0xe42d}}, + {{0x011e1361, 0x1dcb1d5a, 0x1e77eb9d, 0x1c9d5c06, 0x33853032, 0x0e33aff7, 0x184b0d8b, 0x218b1b8b, 0x6413}}} + }, + { + /* 1*16^51*G: */ + {{{0x366642be, 0x376d64a0, 0x158ba889, 0x0d241c5f, 0x0dfa8bce, 0x002bd1a0, 0x30c2f91b, 0x1de30119, 0x146a}}, + {{0x3d83efd0, 0x02ca5d20, 0x37e5ed1d, 0x2aa5c74b, 0x14b2870a, 0x1a609fe7, 0x0028add6, 0x383b0cd5, 0xb318}}}, + /* 3*16^51*G: */ + {{{0x27315443, 0x364e1ce0, 0x2e867299, 0x1e6ef552, 0x2142a13d, 0x32266082, 0x0935ff42, 0x1b010198, 0xfc69}}, + {{0x17d28960, 0x1243582d, 0x09bd1b17, 0x1ffd2184, 0x1677b548, 0x0387375a, 0x35892bbf, 0x09fafe0e, 0xe0ce}}}, + /* 5*16^51*G: */ + {{{0x16fdb4eb, 0x06ecbd70, 0x22e6a79d, 0x28f75e71, 0x3eb0928f, 0x15a8d58a, 0x3f2ad1ae, 0x3c887fd3, 0x974a}}, + {{0x29f6f484, 0x10270f7e, 0x3ffc2348, 0x0715ca8e, 0x0090ed11, 0x0790f40b, 0x003ca64d, 0x0e1f54d4, 0x5552}}}, + /* 7*16^51*G: */ + {{{0x1d5aeee3, 0x0e412b6d, 0x258c8137, 0x0a12f0d9, 0x1270c5e8, 0x086ce99a, 0x2398b091, 0x2d66d277, 0x5baa}}, + {{0x30f69717, 0x0b4a6bed, 0x3d31eed8, 0x1777276a, 0x3fdaf721, 0x28021987, 0x37e856e5, 0x1fd85f03, 0x8a57}}}, + /* 9*16^51*G: */ + {{{0x35726890, 0x146c7913, 0x0837d158, 0x24097fab, 0x110a0ee5, 0x0cbf3afe, 0x1c43d010, 0x17e9fad2, 0xfb68}}, + {{0x3835783a, 0x01baa3ce, 0x10e79b26, 0x29b2c4ba, 0x24ba094f, 0x3285b661, 0x25e2e869, 0x37c8b263, 0xd750}}}, + /* 11*16^51*G: */ + {{{0x28bca48a, 0x1192fc4e, 0x03df62f5, 0x2d357d3a, 0x07f71d78, 0x09ee470a, 0x2995a0ab, 0x23fd9678, 0x5de5}}, + {{0x12fd41cd, 0x21e53a03, 0x20f8aa95, 0x396f6713, 0x2d3c843f, 0x2988f094, 0x19b55309, 0x0ecf600d, 0x685a}}}, + /* 13*16^51*G: */ + {{{0x25ef63b6, 0x378e0d13, 0x31b182eb, 0x2d34059c, 0x0fc1c85a, 0x2dff68ed, 0x218bfaf1, 0x09737ab5, 0x6f18}}, + {{0x05c655f3, 0x0b211b3d, 0x27f94541, 0x22569900, 0x3334553c, 0x108135e0, 0x1911b98f, 0x1f9f7564, 0xff09}}}, + /* 15*16^51*G: */ + {{{0x34a63f3b, 0x2d411fb7, 0x178f9727, 0x080ec066, 0x36c76583, 0x1c457d79, 0x2a376b58, 0x2e257dd8, 0xc5ec}}, + {{0x05005024, 0x14fcdd1a, 0x230bee5b, 0x3ad97b97, 0x1233ec8b, 0x290163fe, 0x081f374e, 0x0946065e, 0x2225}}} + }, + { + /* 1*16^52*G: */ + {{{0x3180eef9, 0x35daa1e4, 0x228b9776, 0x00048826, 0x207b128d, 0x2b3aec6a, 0x2e5f07e3, 0x303d8748, 0xfa50}}, + {{0x3f4f2811, 0x233635f4, 0x17a213b3, 0x1a0ca4e9, 0x01a68a5e, 0x334a1c8a, 0x3eba9b72, 0x31a488e5, 0x6b84}}}, + /* 3*16^52*G: */ + {{{0x11da5e12, 0x07b838ce, 0x1cacb297, 0x31829005, 0x1ca2b6a9, 0x0ca7e4e8, 0x1e31bcda, 0x0b8f10de, 0xf750}}, + {{0x0385f4eb, 0x292e717a, 0x325cebc7, 0x21b4cbbd, 0x1672047b, 0x1c25170f, 0x0fafd599, 0x3d7b759f, 0x3c57}}}, + /* 5*16^52*G: */ + {{{0x10b7d105, 0x01d24cc4, 0x0e57c9f2, 0x329712e5, 0x3455b3f4, 0x13d98938, 0x25862a3a, 0x1e3e60eb, 0x12fe}}, + {{0x1f794a60, 0x162b1bee, 0x2ee90b84, 0x3b389975, 0x27cb771d, 0x2d6a8666, 0x2bcf7786, 0x3c68ce35, 0x2062}}}, + /* 7*16^52*G: */ + {{{0x1e0c5d05, 0x188760ce, 0x2572daff, 0x039b142a, 0x084b1a48, 0x12ec40a0, 0x3473d58c, 0x30c4d1f7, 0x76aa}}, + {{0x11ece63e, 0x159866dd, 0x15e6ee35, 0x048973c0, 0x02625f4b, 0x3ccb20c8, 0x070efabe, 0x1dbbc357, 0xef55}}}, + /* 9*16^52*G: */ + {{{0x3c53c086, 0x389bd217, 0x09a1aec9, 0x2d570d27, 0x288104c6, 0x1830c517, 0x05ccc87e, 0x3f96ef97, 0xa663}}, + {{0x25016201, 0x1a7140ca, 0x3994fc0e, 0x07b3295c, 0x023dc399, 0x2c40b226, 0x11fbf5d1, 0x265fdac8, 0xb541}}}, + /* 11*16^52*G: */ + {{{0x0b758574, 0x2b6007b5, 0x34f9c6e9, 0x0c99a250, 0x22bdf3d8, 0x328409eb, 0x2cd825b7, 0x149e8081, 0xde95}}, + {{0x3b67232a, 0x2df7c7f3, 0x15a2deb4, 0x39a84145, 0x169ed7ba, 0x077211fc, 0x3d14e4e2, 0x3815ab24, 0x4cd3}}}, + /* 13*16^52*G: */ + {{{0x3d85474f, 0x1de6e2af, 0x1634668d, 0x13128ae2, 0x385aea89, 0x3732f911, 0x32addbfe, 0x2f3819b4, 0x8da6}}, + {{0x3d7b4ef7, 0x3f7e71f4, 0x1dbdd7a5, 0x073164c1, 0x1dfff10b, 0x377d741c, 0x2d4ff84f, 0x1b1abcc7, 0x13fc}}}, + /* 15*16^52*G: */ + {{{0x3dd042ea, 0x2d750959, 0x18eafd06, 0x3e89a991, 0x3c93beeb, 0x3599278c, 0x3ba39b1b, 0x2b31f3ec, 0x7329}}, + {{0x2f5c94a1, 0x36a33fb0, 0x1fab4f0a, 0x1225dcc7, 0x2b68ee18, 0x2139e53e, 0x36f14892, 0x124d506d, 0x9272}}} + }, + { + /* 1*16^53*G: */ + {{{0x1f067ec2, 0x394f4cad, 0x1bba5220, 0x0a22ad75, 0x08e8421a, 0x16fdadf6, 0x21a11b1a, 0x1874329c, 0xda1d}}, + {{0x1ad836f1, 0x157ee83c, 0x279b48a6, 0x29ce2674, 0x091e2966, 0x01d98587, 0x1306c79c, 0x3d569f26, 0x8157}}}, + /* 3*16^53*G: */ + {{{0x3a95a8db, 0x1761dccb, 0x39d36f61, 0x0fb03111, 0x1b1723b8, 0x25991a64, 0x3dd0419e, 0x036918c0, 0xe3e9}}, + {{0x1b0d1cf9, 0x005b3dfc, 0x0984d3d1, 0x2c7be5f3, 0x02e76afb, 0x3eaa431c, 0x0178bb00, 0x0ef0015b, 0xfbe5}}}, + /* 5*16^53*G: */ + {{{0x112ee214, 0x1eabf590, 0x19315401, 0x0a93a5e5, 0x00c01c78, 0x19437f57, 0x3d775a8b, 0x3fb1ccb8, 0x9f4f}}, + {{0x1085f37a, 0x3bd10889, 0x3c880283, 0x066da4c2, 0x35c69d97, 0x259a0bf5, 0x22f2e60e, 0x38b84c63, 0x639c}}}, + /* 7*16^53*G: */ + {{{0x1f61a0a5, 0x22da0514, 0x3c14e3ef, 0x0494f86c, 0x040b2c4b, 0x0682907d, 0x34ac1b17, 0x188b5044, 0x431f}}, + {{0x38cef899, 0x1adedff9, 0x15657724, 0x2eaa810d, 0x23aa7241, 0x3799465c, 0x2438f6d6, 0x0c9ff9ea, 0xa298}}}, + /* 9*16^53*G: */ + {{{0x27748503, 0x2b099f55, 0x31328e7c, 0x1b8391dc, 0x0a12ac0e, 0x18bbce7e, 0x38fb86cb, 0x2eb77b39, 0x993d}}, + {{0x3eb0cee2, 0x2e9cd84d, 0x38adaa49, 0x3e1efda6, 0x21f51a17, 0x3de11e1e, 0x1eeeb785, 0x2a7ba15a, 0xa521}}}, + /* 11*16^53*G: */ + {{{0x26d23d80, 0x37a889d6, 0x2474d478, 0x02f447c9, 0x0962c0e1, 0x250c72e4, 0x15ea5a33, 0x1eae81ab, 0x75f1}}, + {{0x280dd57e, 0x21aa16c0, 0x34ea5909, 0x0bfefb6e, 0x1b629237, 0x31f42fc6, 0x39a80c7f, 0x18bf8558, 0xa07a}}}, + /* 13*16^53*G: */ + {{{0x21ad3413, 0x38ae6db5, 0x327d684a, 0x2e700100, 0x387b7a8d, 0x257d2172, 0x1f4a0a6e, 0x15578476, 0x6678}}, + {{0x3ebca672, 0x09204081, 0x2dc66601, 0x338b454e, 0x0bdf9ea6, 0x099b649f, 0x0f646925, 0x368f789e, 0x510d}}}, + /* 15*16^53*G: */ + {{{0x06cc8563, 0x3002bd6c, 0x3e101eaa, 0x0937d6ff, 0x16368892, 0x320af606, 0x27748ada, 0x128d8b36, 0xebdc}}, + {{0x2394ccfa, 0x26c5ef3a, 0x1204f924, 0x3101e492, 0x1d4f07be, 0x3b8d79b3, 0x2d35f9b1, 0x0c513a15, 0x659a}}} + }, + { + /* 1*16^54*G: */ + {{{0x0d064e13, 0x29cec184, 0x06f1e062, 0x0c477811, 0x3d416615, 0x17fe63a3, 0x30690721, 0x20bfc325, 0xa8e2}}, + {{0x11f4cc0c, 0x3bdf1cc4, 0x0dd6bd6c, 0x19e68f94, 0x2515888b, 0x2dfcf16c, 0x01c09abf, 0x0d56e36e, 0x7f97}}}, + /* 3*16^54*G: */ + {{{0x3a3979b5, 0x0a8666c2, 0x27e829e2, 0x0a23e379, 0x240e50ba, 0x0dfc2c7b, 0x1e26327f, 0x01f1736b, 0xae22}}, + {{0x0450fa6f, 0x23cf359a, 0x3d4f8896, 0x2a1edf4d, 0x2d7060fc, 0x3249148e, 0x39f71ad4, 0x3f944301, 0xea91}}}, + /* 5*16^54*G: */ + {{{0x0efca824, 0x10406440, 0x22164fae, 0x2f8313fa, 0x185461e0, 0x31504019, 0x2ace59ce, 0x3b432b5c, 0xcb8d}}, + {{0x0f227361, 0x0502f416, 0x3931742f, 0x2b47f7f1, 0x2ccbc496, 0x05b121e8, 0x188c85b3, 0x0023dd03, 0x33a5}}}, + /* 7*16^54*G: */ + {{{0x3bcbd327, 0x1046d368, 0x1e4aaee9, 0x13821488, 0x276ed6b0, 0x2524035f, 0x1836708e, 0x0eca62bc, 0xb0c5}}, + {{0x2d7be436, 0x185af128, 0x0636a0f1, 0x0a88831d, 0x26b2afd8, 0x3da9806d, 0x17ea1638, 0x25d007ef, 0xee2a}}}, + /* 9*16^54*G: */ + {{{0x17b836a1, 0x39bbed8e, 0x3679ef7d, 0x019017fd, 0x37f526c8, 0x2218bb39, 0x1b920d4d, 0x29cfcca7, 0x6f6b}}, + {{0x06832b84, 0x36f7cbec, 0x0e1ff934, 0x264314a2, 0x3ee9c0d8, 0x02e29016, 0x3c18e3db, 0x2285ffd7, 0xdc77}}}, + /* 11*16^54*G: */ + {{{0x1eb39ede, 0x2bb8d082, 0x30612d42, 0x02200cb5, 0x02436031, 0x3fd19f84, 0x22af4bbc, 0x069f71d0, 0x7d47}}, + {{0x2bf6607e, 0x326f3652, 0x022a8fd0, 0x2573df47, 0x3c86fa77, 0x2088c7bf, 0x2856507b, 0x1ec67ce9, 0x004a}}}, + /* 13*16^54*G: */ + {{{0x165eb1c1, 0x15b52789, 0x1ae5c5aa, 0x335d59f3, 0x02f0967f, 0x03f30c66, 0x33fac707, 0x1458fe6d, 0xf002}}, + {{0x2dde2ae0, 0x369f5c11, 0x2cd11e57, 0x1dbfd735, 0x26afed85, 0x1ad29768, 0x120df4c6, 0x2a7a220f, 0x054e}}}, + /* 15*16^54*G: */ + {{{0x1ac32c64, 0x33cd424f, 0x0ae4bf84, 0x0dbf80fb, 0x07715e0e, 0x013a543d, 0x123aa0f7, 0x0500007b, 0xac12}}, + {{0x1eb1a867, 0x204ab6eb, 0x253f0898, 0x16974e96, 0x0499a3ed, 0x02da55cc, 0x38baf187, 0x2f32eb0c, 0xce8e}}} + }, + { + /* 1*16^55*G: */ + {{{0x0319497c, 0x0bce0b7a, 0x12508c02, 0x166c7e94, 0x13cab15d, 0x2795b9a4, 0x285872d3, 0x14ee7268, 0x174a}}, + {{0x079afa73, 0x0f684eb0, 0x0b985438, 0x1ace8763, 0x07f9e664, 0x10557cb1, 0x09c1657b, 0x370deaff, 0xccc9}}}, + /* 3*16^55*G: */ + {{{0x354b8367, 0x25201cf5, 0x3d506bfe, 0x1d6ddf59, 0x036a5db7, 0x2a975161, 0x2526e40c, 0x0252b911, 0x5e5a}}, + {{0x11ce85ca, 0x14ca6a76, 0x1e5ffa44, 0x1aaa7bcf, 0x2a4b7a79, 0x2407c55c, 0x15e05c2c, 0x3e32691e, 0xae8a}}}, + /* 5*16^55*G: */ + {{{0x17b10d9d, 0x06615e4e, 0x11f8fcaf, 0x294bc627, 0x0cb82de6, 0x332e0cc4, 0x02e859de, 0x382b6e5c, 0x00d4}}, + {{0x3140dced, 0x20840121, 0x0e2d923e, 0x1626325e, 0x2287f70b, 0x0be1190c, 0x3640947d, 0x0066060d, 0x87b8}}}, + /* 7*16^55*G: */ + {{{0x1c9caee8, 0x02046982, 0x1a270bb2, 0x0b88116c, 0x04a66763, 0x1e866bbb, 0x374c0f6f, 0x1484da3b, 0x0366}}, + {{0x3772b711, 0x2a7b1a8e, 0x295ba7f0, 0x32ea624c, 0x26944501, 0x27f1a06e, 0x3ded9994, 0x30cacaa4, 0x1f18}}}, + /* 9*16^55*G: */ + {{{0x1446c85c, 0x0ffe5d46, 0x201c0635, 0x0df78239, 0x36c6eade, 0x19db114f, 0x38f1faa0, 0x24415bf6, 0x0e58}}, + {{0x2148972e, 0x3db1df9c, 0x0cddadd5, 0x2408d3a0, 0x081898f4, 0x1d062ebd, 0x27bda0ec, 0x1217c47e, 0xe39a}}}, + /* 11*16^55*G: */ + {{{0x022e1259, 0x3c62b7cf, 0x281362af, 0x05ce6901, 0x07777193, 0x33d7ea80, 0x1463f2b6, 0x049b49bc, 0xa740}}, + {{0x334a5f43, 0x3ddc5c90, 0x31d6dad5, 0x21979d4e, 0x3c7ee517, 0x17c5d299, 0x0f1ff1b0, 0x3feebc65, 0x05a9}}}, + /* 13*16^55*G: */ + {{{0x0b08f1fe, 0x22285e8f, 0x3a087bfd, 0x339fb9c2, 0x02d177d7, 0x1015d976, 0x074e4a65, 0x2e085b65, 0x87e4}}, + {{0x2ed5e2ec, 0x17dd2b26, 0x2786d9d7, 0x0bc8f6f5, 0x38c2cc6e, 0x35fe3a8b, 0x348cecd7, 0x0eb01d98, 0xf74e}}}, + /* 15*16^55*G: */ + {{{0x21c4d15c, 0x2a1c039a, 0x3c0e74b9, 0x17a9efc1, 0x254a4410, 0x308b0304, 0x279a5a92, 0x06d18ffa, 0x35ea}}, + {{0x3f3fe1ea, 0x324e6ebd, 0x065095ed, 0x18cea80c, 0x0d3b185d, 0x23e97f5d, 0x2d2cd788, 0x245946e7, 0xad21}}} + }, + { + /* 1*16^56*G: */ + {{{0x1475b7ba, 0x213f7fc2, 0x0918b3d8, 0x0e79cc39, 0x018cdbe0, 0x395fb7d4, 0x3785c3d3, 0x25a60650, 0x9593}}, + {{0x3524f2fd, 0x26e2afe1, 0x0709385e, 0x194fd932, 0x1cd6849c, 0x00e1a92e, 0x331dd8ba, 0x154a2230, 0x2e7e}}}, + /* 3*16^56*G: */ + {{{0x0fd69985, 0x02717764, 0x1df72aea, 0x0c2732db, 0x0ccf149f, 0x3da437ef, 0x32f7e788, 0x1d9d73ad, 0x0ae9}}, + {{0x1409a003, 0x2723ad04, 0x2ee1aff8, 0x2e67505e, 0x1a54c5d0, 0x237fb814, 0x08d14e9b, 0x265cfdb9, 0x9121}}}, + /* 5*16^56*G: */ + {{{0x19262b90, 0x37064f7f, 0x23cc29a9, 0x08f1307f, 0x025d1fb7, 0x197c5de0, 0x1612ec9b, 0x218a96b0, 0x2b15}}, + {{0x083d7557, 0x24665b99, 0x19489a49, 0x14d25c3e, 0x0749066f, 0x0c354b6a, 0x233faa7a, 0x014f6a82, 0x2eb0}}}, + /* 7*16^56*G: */ + {{{0x28e7be40, 0x0fe5c532, 0x1040ee59, 0x34b22524, 0x24769af2, 0x2570585b, 0x2ee677ee, 0x3abb46a5, 0x6af9}}, + {{0x2e387e1c, 0x2905b809, 0x0f59569f, 0x38fd99a8, 0x07dc8145, 0x27a90a0d, 0x06649670, 0x0a845a40, 0xb381}}}, + /* 9*16^56*G: */ + {{{0x3482801e, 0x09adbe83, 0x1bd4155d, 0x1e53e2f1, 0x38d6f940, 0x2aad0932, 0x0144eeb3, 0x1a3b8111, 0x5966}}, + {{0x04870c37, 0x11dc523c, 0x3d3535ad, 0x2db072d8, 0x31304e8d, 0x23e5821d, 0x2ef5f1ec, 0x282a16ee, 0x949a}}}, + /* 11*16^56*G: */ + {{{0x032c19fd, 0x1326cb9f, 0x18028c3e, 0x32ae3a41, 0x170b5b4a, 0x3d345ead, 0x050762fd, 0x346206d4, 0xbe84}}, + {{0x32f1281f, 0x1da5294d, 0x250dc376, 0x1569fd57, 0x08399479, 0x3997d20c, 0x050944d1, 0x1832ccb7, 0xeff9}}}, + /* 13*16^56*G: */ + {{{0x16c69482, 0x346dd7f5, 0x32fa167b, 0x3aad5004, 0x32bc88cb, 0x15c9d32b, 0x17ee541f, 0x280c5303, 0x9867}}, + {{0x2f792cd7, 0x1bc18451, 0x15628a91, 0x189173d4, 0x3a99639e, 0x24b556c6, 0x0834f9c7, 0x18568ec4, 0xd02e}}}, + /* 15*16^56*G: */ + {{{0x1d557aa1, 0x2288e764, 0x101fc297, 0x0764bfb3, 0x19d6abdf, 0x1fcba802, 0x0815a592, 0x3c915036, 0xa866}}, + {{0x01430634, 0x2606eed3, 0x0611a4b7, 0x3ada719f, 0x30e13961, 0x0f63e976, 0x22b44d79, 0x0e7daa00, 0xb587}}} + }, + { + /* 1*16^57*G: */ + {{{0x1d82b151, 0x2d44d032, 0x21fba2db, 0x28290f55, 0x109a8fcc, 0x168454ec, 0x01e56d64, 0x0e942b90, 0xd2a6}}, + {{0x1cf89405, 0x105085d3, 0x084ca52d, 0x03dd42bd, 0x148220a7, 0x2bb962ca, 0x3fcb7565, 0x21bed910, 0xe82d}}}, + /* 3*16^57*G: */ + {{{0x2e4b3ba0, 0x2167d8d7, 0x18bf1f17, 0x0aafbd7c, 0x3f245f5c, 0x385c3cc6, 0x3fb73bef, 0x04414887, 0x4108}}, + {{0x17525595, 0x21a58770, 0x1a064554, 0x0d926159, 0x2b849813, 0x2996b875, 0x35668f2c, 0x3cda5dbf, 0xdc37}}}, + /* 5*16^57*G: */ + {{{0x13d98ded, 0x18a726e2, 0x38a02184, 0x37c8a0ce, 0x31d65edb, 0x3c8a6414, 0x0c0c8c8c, 0x2884285b, 0x63a2}}, + {{0x20d1cfc2, 0x06465f53, 0x1c7873a5, 0x2afda802, 0x2d94461f, 0x140cc953, 0x2c76fd06, 0x10b8b9ff, 0x882b}}}, + /* 7*16^57*G: */ + {{{0x38045445, 0x2a186942, 0x01e8d7ee, 0x3fdcdc64, 0x17bef080, 0x04b8b975, 0x167ca3df, 0x20575127, 0x0c15}}, + {{0x0054a206, 0x053e1f55, 0x258cea32, 0x0c15390d, 0x23cd28ba, 0x24f0ed99, 0x14115d0a, 0x35828eba, 0x2f30}}}, + /* 9*16^57*G: */ + {{{0x03857faf, 0x3a448e73, 0x29619701, 0x0bf2b787, 0x28ef7f88, 0x1eea3d20, 0x28a9c0d5, 0x3adae26b, 0xc757}}, + {{0x20584ca4, 0x07676c32, 0x01894c10, 0x1f4c4344, 0x3ec61b62, 0x0da7c822, 0x3ff36257, 0x1673f348, 0xf03a}}}, + /* 11*16^57*G: */ + {{{0x1459225d, 0x3934613d, 0x18858d10, 0x3ebddf8b, 0x1c02a244, 0x17502646, 0x3a0d0f81, 0x18ebab6b, 0xfa80}}, + {{0x3ece1507, 0x28adf8ed, 0x007c59c3, 0x0adb0db4, 0x0c425c0a, 0x37888209, 0x0c069160, 0x07e415f0, 0x0ba7}}}, + /* 13*16^57*G: */ + {{{0x16f0d044, 0x19e7fa50, 0x09e61a79, 0x2ea7f524, 0x2ee0a5aa, 0x3da73e18, 0x257a89e2, 0x28f16740, 0x658c}}, + {{0x37cb872d, 0x3747ccbb, 0x018ce89a, 0x2859d8f1, 0x3bd37655, 0x197589c4, 0x225460f1, 0x304ddeba, 0xae5c}}}, + /* 15*16^57*G: */ + {{{0x3696756d, 0x2d6b255c, 0x2561417a, 0x1abc5815, 0x3f305c67, 0x30660d74, 0x1f2bace4, 0x12d2abe4, 0x31c9}}, + {{0x1e08ae78, 0x2f117a37, 0x2ad1070a, 0x2bb7f2b9, 0x34160683, 0x2e2d66ab, 0x283a9bf4, 0x2212d55b, 0xf80f}}} + }, + { + /* 1*16^58*G: */ + {{{0x1617e073, 0x10dbe6d1, 0x039317b3, 0x2b2f6f4e, 0x0fdc866b, 0x39e25b5f, 0x31eb890e, 0x1f88cd51, 0x6458}}, + {{0x1faf6589, 0x20a6797a, 0x33aeab35, 0x2e428e44, 0x0299a185, 0x1b75911f, 0x102e2ae9, 0x33756fda, 0xd99f}}}, + /* 3*16^58*G: */ + {{{0x0e103dd6, 0x37dc51c8, 0x0004859a, 0x1181301f, 0x12a17ac3, 0x084f3f16, 0x203f836a, 0x1ef55690, 0xbc47}}, + {{0x16f7c343, 0x0e420b63, 0x23b44ac6, 0x0a4d5cb1, 0x1ea6395d, 0x2b154b1b, 0x0dd526cb, 0x07890a6a, 0xe31e}}}, + /* 5*16^58*G: */ + {{{0x144eab31, 0x34370ec3, 0x0e634907, 0x316bc501, 0x3bf8e80a, 0x0ed08c99, 0x3b838030, 0x2d3f969a, 0x589d}}, + {{0x11361f6a, 0x106baf9d, 0x148f8db9, 0x18439548, 0x3d90f31f, 0x1c188092, 0x2a2a4f60, 0x11170422, 0x6255}}}, + /* 7*16^58*G: */ + {{{0x1a0c2c41, 0x2fe585ca, 0x20336c67, 0x20c70715, 0x2edb7c42, 0x286182b5, 0x22fa2ea8, 0x2ccdf45b, 0x1339}}, + {{0x29f1bc2b, 0x217c152e, 0x1e923a41, 0x0489fe1f, 0x13a3406b, 0x0c903f44, 0x3ae5ba7a, 0x0a58d8b1, 0x9f9b}}}, + /* 9*16^58*G: */ + {{{0x18fc47af, 0x1c12c7e1, 0x2c0cdec3, 0x377fb20c, 0x01b568a8, 0x00ca6d40, 0x3cf17cc5, 0x2ee844d8, 0x7ff3}}, + {{0x39ba43a7, 0x3e185933, 0x18bac297, 0x294ec6b4, 0x33446b17, 0x32246dd1, 0x0a629a0b, 0x29eba006, 0x1f6b}}}, + /* 11*16^58*G: */ + {{{0x15213775, 0x06135802, 0x3d42a990, 0x2d0a4ec8, 0x2c7f6100, 0x07a4e57f, 0x360bb614, 0x1c118f3a, 0x8ec6}}, + {{0x3841ffff, 0x38043cf9, 0x0cf51e90, 0x36a6282f, 0x2dee0e71, 0x190d0573, 0x25be306e, 0x299be836, 0x8f58}}}, + /* 13*16^58*G: */ + {{{0x3452abbb, 0x32cffe34, 0x2b95c2e3, 0x1aa9cbf8, 0x15d495ae, 0x2eb0ffb6, 0x301bb89d, 0x186d1079, 0x83de}}, + {{0x054eb66e, 0x28145dac, 0x3ce42918, 0x2717cdae, 0x0e1563d7, 0x3edabe31, 0x0609fa6b, 0x38cd28d3, 0x32f0}}}, + /* 15*16^58*G: */ + {{{0x359276f1, 0x25a2309b, 0x2a17b15e, 0x2b896ca4, 0x3cd86833, 0x2ed7003d, 0x0c1db1a8, 0x18e263d4, 0x3d76}}, + {{0x059cbcb3, 0x0792996e, 0x1b197860, 0x08660806, 0x18333ef3, 0x1db8d36b, 0x07ddb609, 0x1a5cde86, 0xd376}}} + }, + { + /* 1*16^59*G: */ + {{{0x1d45e458, 0x1635b21b, 0x250e7fd3, 0x02a9b3a8, 0x09de042f, 0x151b4f95, 0x0d885b3a, 0x2f783939, 0x8481}}, + {{0x1779057e, 0x3592c6d6, 0x3262e556, 0x029e710a, 0x2cb2ca90, 0x096fce73, 0x004dd84a, 0x1ee32e95, 0x38ee}}}, + /* 3*16^59*G: */ + {{{0x152da17d, 0x18283e90, 0x0d0646b1, 0x3704f6c2, 0x200bc811, 0x139ac17f, 0x18c5f089, 0x3b4783d4, 0x3bea}}, + {{0x2cc768d2, 0x39c12617, 0x1fec416c, 0x3379dee3, 0x00e1b554, 0x12a2fafa, 0x37acdfef, 0x35fd56bf, 0xc3b0}}}, + /* 5*16^59*G: */ + {{{0x3a4edcc5, 0x0d3e85f6, 0x20311b72, 0x138c8850, 0x275997e7, 0x0b7f00e4, 0x09d61875, 0x36e832f7, 0x6e73}}, + {{0x159da0e4, 0x2cc7df37, 0x00679037, 0x229df69c, 0x02869327, 0x11542222, 0x2cc48bea, 0x307f127b, 0xee0a}}}, + /* 7*16^59*G: */ + {{{0x0a80b979, 0x02713109, 0x29abb314, 0x243d7e8c, 0x07c31004, 0x1f65faa9, 0x1b592762, 0x37624df9, 0x7706}}, + {{0x0126cfde, 0x133d2041, 0x17efe321, 0x3e828d3f, 0x2a9c7117, 0x2375e647, 0x3b714777, 0x2a609f56, 0x8a02}}}, + /* 9*16^59*G: */ + {{{0x326fe285, 0x336e712d, 0x13ef127d, 0x16eb0a50, 0x39e06aa4, 0x3cf1e907, 0x3c0f80d2, 0x08b164a6, 0x16d4}}, + {{0x0155b441, 0x0f83ff9b, 0x3364d423, 0x0fc3044d, 0x3531b1e9, 0x2df9a698, 0x22641a8a, 0x223e9478, 0x0df8}}}, + /* 11*16^59*G: */ + {{{0x3acfa513, 0x38c42f2a, 0x260e3aea, 0x0901e7e6, 0x356a9c4e, 0x28d11d43, 0x36d63aa5, 0x0391fbb1, 0x1fcc}}, + {{0x107afc9c, 0x141d6e90, 0x09839187, 0x3b7b7459, 0x39f9b44b, 0x38e1d50c, 0x35478b48, 0x30681078, 0x165d}}}, + /* 13*16^59*G: */ + {{{0x3edc69b2, 0x0689c1f3, 0x26b77172, 0x0298226c, 0x0aa386a5, 0x190c10d7, 0x0b8a1730, 0x241ceb5b, 0xc12b}}, + {{0x20dd41dd, 0x0caba6c0, 0x127b2a00, 0x3b876f8f, 0x094976b8, 0x1cb7227e, 0x0cdf1d97, 0x310ff94d, 0x3173}}}, + /* 15*16^59*G: */ + {{{0x3961fe4d, 0x2dbd6177, 0x3107197a, 0x05221be2, 0x2ca73e8a, 0x0fa4c4c4, 0x27a8fa3f, 0x2fe1770c, 0xd059}}, + {{0x2ae823c2, 0x264d6c19, 0x0dab64cb, 0x0e22e87d, 0x0955b4fd, 0x01d97721, 0x3525e3fe, 0x1e983022, 0x4510}}} + }, + { + /* 1*16^60*G: */ + {{{0x2caf666b, 0x3358c0fd, 0x0b1ce30b, 0x3f3fb4f1, 0x17f4637f, 0x1a5e6ba0, 0x102aa62b, 0x1295e9e0, 0x1346}}, + {{0x3f6ecc27, 0x3d256a41, 0x10942e13, 0x3cc02a07, 0x0cb0ca48, 0x390cd14f, 0x14580ef7, 0x05640118, 0x69be}}}, + /* 3*16^60*G: */ + {{{0x0eca5f51, 0x085ac826, 0x0fc9aebf, 0x3a85c6e5, 0x05b5cfdd, 0x3b5acafc, 0x2e6962c6, 0x35453767, 0xdde9}}, + {{0x10c638f7, 0x2b5a69cf, 0x289571f9, 0x3fbafa37, 0x3f8f0950, 0x07cd2c29, 0x28111d89, 0x1a44cf38, 0xb84e}}}, + /* 5*16^60*G: */ + {{{0x199c88e4, 0x3e41ac16, 0x0ad46ec2, 0x3b544f88, 0x204b179a, 0x3d01bac4, 0x193736e9, 0x188408da, 0xfd1a}}, + {{0x195bc8df, 0x27232459, 0x1cc00f29, 0x1adc7525, 0x177782dc, 0x0f01a552, 0x0c20bfb1, 0x1ed52e72, 0x1ac9}}}, + /* 7*16^60*G: */ + {{{0x1f8018ce, 0x35456d6d, 0x1892d68b, 0x0b695ce3, 0x086dc7cf, 0x3ff393cb, 0x296b9f13, 0x214c7630, 0x4ee4}}, + {{0x1e48381f, 0x30d6986c, 0x0e806013, 0x01d25c6d, 0x07c5e671, 0x2d102343, 0x3f8b5fc7, 0x27b52042, 0xb68f}}}, + /* 9*16^60*G: */ + {{{0x31473678, 0x0a14ba47, 0x14392f70, 0x2815e542, 0x38c070cb, 0x38c53156, 0x000dbff5, 0x33270d31, 0xfd76}}, + {{0x0d144f4f, 0x38593baa, 0x001c8437, 0x18a3bb85, 0x032cd660, 0x3b829cf4, 0x143dae0f, 0x1950de1c, 0xf204}}}, + /* 11*16^60*G: */ + {{{0x0d7a2193, 0x3c02dc52, 0x197546ed, 0x1a47913c, 0x34ea212c, 0x1b3a09d2, 0x3b40219e, 0x2ae8cc48, 0x85a2}}, + {{0x30cdcf3a, 0x3c320f52, 0x03b12427, 0x31b6b7e7, 0x0c029fe1, 0x31820b47, 0x30516d82, 0x2615faca, 0x9c12}}}, + /* 13*16^60*G: */ + {{{0x377568b0, 0x16c0c16c, 0x1e03b053, 0x2ba37406, 0x03650f35, 0x2db5b15e, 0x3fe74440, 0x36ff1cf3, 0xd25d}}, + {{0x1f39929c, 0x0284e49b, 0x23c3f006, 0x089ce207, 0x27d92b83, 0x2bbdd337, 0x048938be, 0x3fdd64fe, 0x7a3a}}}, + /* 15*16^60*G: */ + {{{0x271d7c13, 0x17f94462, 0x20ffa385, 0x06ad7dfe, 0x2ac80564, 0x01fa6a5e, 0x14a7255f, 0x0d4c50fa, 0x4581}}, + {{0x3aff63cf, 0x18e2f154, 0x2bd96b99, 0x08019550, 0x1d69c970, 0x3d43c5df, 0x39ad8b57, 0x163b0525, 0x9f58}}} + }, + { + /* 1*16^61*G: */ + {{{0x2d83f366, 0x2b68e834, 0x2f28588c, 0x36733b78, 0x1dc97a0c, 0x3d0c2f30, 0x3fe2e9ae, 0x277d6dc4, 0xbc4a}}, + {{0x181f33c1, 0x1d635999, 0x2547b16d, 0x3a2a7efe, 0x3798caa6, 0x24deb7d2, 0x05c06383, 0x20729b9e, 0x0d3a}}}, + /* 3*16^61*G: */ + {{{0x3712be3c, 0x01a8b8cb, 0x2146a66b, 0x257c63b6, 0x00153472, 0x1c976eac, 0x1b378d3c, 0x0d2764cc, 0x39d7}}, + {{0x1c6ff65c, 0x30c067d0, 0x0a41644c, 0x17bde97b, 0x2812e8ef, 0x09d55319, 0x33bf7fb1, 0x26d3d5bb, 0x8f92}}}, + /* 5*16^61*G: */ + {{{0x1f77f22b, 0x2ab93ef3, 0x0f82e035, 0x265c8e65, 0x15af26c6, 0x0735b0a6, 0x01dd09e5, 0x2985fdf7, 0xf0cb}}, + {{0x1909a03c, 0x3f238b1d, 0x0a095661, 0x3c631fa4, 0x16d04004, 0x0c9b0d94, 0x1df989ef, 0x2ad0c4fe, 0x1a25}}}, + /* 7*16^61*G: */ + {{{0x06509c12, 0x22b37353, 0x3d1f4765, 0x1aff88d6, 0x3268ed8d, 0x05c3a361, 0x154d321d, 0x1eae76c8, 0x381d}}, + {{0x2eb46102, 0x1190aa38, 0x0e6eaf75, 0x160a161b, 0x2581e720, 0x34915ce9, 0x23da9eb5, 0x2ad6dff6, 0xa47a}}}, + /* 9*16^61*G: */ + {{{0x384fe955, 0x36ced358, 0x063bce48, 0x2655a968, 0x0c8a53f6, 0x0edcf9a5, 0x387e6479, 0x3c1519ea, 0xa703}}, + {{0x161344bd, 0x09acbbef, 0x197277fa, 0x27858a71, 0x19199b53, 0x29e4b5ac, 0x047adc0e, 0x3e4d68ac, 0xd500}}}, + /* 11*16^61*G: */ + {{{0x06eace58, 0x126595b0, 0x2f3211d3, 0x1f9158e8, 0x13a03f1b, 0x1ab435c1, 0x150d746c, 0x2cf16ab5, 0x73c6}}, + {{0x2af8654e, 0x05c2a45c, 0x3b8d2917, 0x1aa1e36e, 0x2d91c6aa, 0x242644d9, 0x24f741ba, 0x2d291cce, 0x3a2f}}}, + /* 13*16^61*G: */ + {{{0x00181d5e, 0x12ce22fc, 0x15aaf205, 0x1c6cea6e, 0x0eddb8de, 0x0034e870, 0x147fda1d, 0x3cf9d41b, 0xc627}}, + {{0x369f886d, 0x09e40298, 0x1cbe2c39, 0x3dac0152, 0x21f7d68e, 0x1a5804e2, 0x02a63b2d, 0x2775c791, 0xd78f}}}, + /* 15*16^61*G: */ + {{{0x37828b16, 0x138a367e, 0x0a4847f3, 0x11e563ca, 0x06de53a0, 0x17d029bc, 0x3d233fa2, 0x3eaf83b7, 0xbb88}}, + {{0x0aea5df7, 0x1451ce88, 0x3a1e969c, 0x12a05d38, 0x159163ec, 0x37165804, 0x1e8dd345, 0x1dacc13d, 0xb736}}} + }, + { + /* 1*16^62*G: */ + {{{0x25324caa, 0x152acc3f, 0x29472a39, 0x12d978c2, 0x12a32e69, 0x3631d251, 0x18bc0d23, 0x2a5efe0a, 0x8c28}}, + {{0x0bef9482, 0x39c771cf, 0x11cb9459, 0x39e13c11, 0x3cc0eb7a, 0x3fb7cc7d, 0x05193378, 0x0118e8cc, 0x40a3}}}, + /* 3*16^62*G: */ + {{{0x0754dd40, 0x18fa1c55, 0x03466cf8, 0x10898c7f, 0x32f6e9a2, 0x12107f35, 0x0dfcf45b, 0x091c0cb0, 0x9729}}, + {{0x2aa36143, 0x212d24bc, 0x1acaf493, 0x36ba1495, 0x14df3690, 0x171d772f, 0x3ea1dcd1, 0x28910997, 0x91d1}}}, + /* 5*16^62*G: */ + {{{0x0c2ca7ff, 0x30b60bae, 0x1df021a3, 0x00d91765, 0x2f27af18, 0x1e46b568, 0x2796e050, 0x1fe5d602, 0x8963}}, + {{0x30493e68, 0x3b505785, 0x242eab7b, 0x1ef1a8e3, 0x357489f8, 0x2e73c550, 0x08424d57, 0x38492322, 0x2d1f}}}, + /* 7*16^62*G: */ + {{{0x0ca8dd7f, 0x061b58e8, 0x2a1381a6, 0x31ca00d5, 0x1357421b, 0x327680f5, 0x25e092fd, 0x0e39c6f8, 0x3081}}, + {{0x0a92c7f2, 0x1057c91e, 0x34ad915e, 0x05959190, 0x008e18c8, 0x27b11745, 0x0fc925e3, 0x38b4a20a, 0x28d1}}}, + /* 9*16^62*G: */ + {{{0x066a3fb1, 0x037315a2, 0x192e206c, 0x30024a06, 0x36862f6e, 0x15d43216, 0x1eb65d1e, 0x313a0a9b, 0x575f}}, + {{0x102655ad, 0x26e3a42a, 0x2a3af2f0, 0x0ced5cf1, 0x0e87daed, 0x076f0a5e, 0x2fca2d67, 0x36e410a9, 0x6f6e}}}, + /* 11*16^62*G: */ + {{{0x390117df, 0x06daa291, 0x22010292, 0x094eeef3, 0x2a2a8fda, 0x3c9be07b, 0x2ab7a227, 0x240dad93, 0xa5ec}}, + {{0x386462fe, 0x204a04cf, 0x214a363d, 0x21187c15, 0x1fa0f71c, 0x25e60eb4, 0x140400c5, 0x319897b0, 0xb79d}}}, + /* 13*16^62*G: */ + {{{0x172ad712, 0x2c3e5d70, 0x21047290, 0x0e632c37, 0x2349b95a, 0x39e5d851, 0x10b0949d, 0x37fa44cc, 0xa153}}, + {{0x0d48fdd2, 0x2297d94e, 0x2f0b329c, 0x014fca16, 0x31b89abd, 0x0c6357c7, 0x05b2fc48, 0x36104fec, 0xfd94}}}, + /* 15*16^62*G: */ + {{{0x11cf5b3a, 0x0c30dc04, 0x1b5a7810, 0x10cea0ef, 0x2dc824c4, 0x30d34223, 0x14615935, 0x06b1abde, 0x9a54}}, + {{0x36a44ae4, 0x0fd55d7c, 0x21ea52d6, 0x123fb894, 0x0f475f55, 0x386bcda2, 0x06ab7caf, 0x123072c4, 0xb661}}} + }, + { + /* 1*16^63*G: */ + {{{0x1faccae0, 0x2312e844, 0x24bb3374, 0x22cd4316, 0x071fd23c, 0x3653393c, 0x127a8c1d, 0x259984e5, 0x08ea}}, + {{0x0e62b945, 0x16bcd28c, 0x0f0f8e95, 0x2de0efa7, 0x15c5d735, 0x39f033ee, 0x22782e24, 0x3eaef23b, 0x620e}}}, + /* 3*16^63*G: */ + {{{0x26a06f5e, 0x06902d65, 0x2a083702, 0x1064945b, 0x23b716a3, 0x2c350849, 0x0253ac37, 0x093efa85, 0x383b}}, + {{0x13c6e772, 0x227d1e1b, 0x38c2b040, 0x3dab9d2e, 0x2a5a19e8, 0x3d59b553, 0x1ba2044c, 0x1c1ab13b, 0x54cf}}}, + /* 5*16^63*G: */ + {{{0x0638a136, 0x1e5d7075, 0x2838195c, 0x034738cd, 0x0d790c2b, 0x39671ad8, 0x2ed6d789, 0x0cb40f80, 0xe684}}, + {{0x0c6c2584, 0x2bf46042, 0x3357336a, 0x0278faf6, 0x01e6472e, 0x0a9cc0e8, 0x35a6624d, 0x3904e638, 0xca5b}}}, + /* 7*16^63*G: */ + {{{0x16e8c10c, 0x33a1f110, 0x11bd6807, 0x1ca617ce, 0x306e7fb4, 0x3ef7b39c, 0x25c2a0ee, 0x355678bf, 0x395d}}, + {{0x05fe638e, 0x30f5b64c, 0x066922cb, 0x24270137, 0x3a4e274c, 0x04fa1ebf, 0x12ac5d04, 0x37352d16, 0xfd62}}}, + /* 9*16^63*G: */ + {{{0x0d6c14ef, 0x059936c8, 0x2f93c8f5, 0x163f1d41, 0x22648008, 0x3bb56fbb, 0x25dcb9f6, 0x12b70d54, 0x7a51}}, + {{0x0b3fbd13, 0x2b4f861c, 0x2a6e24f7, 0x2fabbdca, 0x0f5c3729, 0x1fc2e532, 0x2e4d8e89, 0x347fb454, 0x56ed}}}, + /* 11*16^63*G: */ + {{{0x0f6d65eb, 0x2a518f41, 0x04021524, 0x26441dd5, 0x108f235a, 0x23bcefd2, 0x1d90d8ea, 0x3f5610c9, 0x1ee1}}, + {{0x1d22941c, 0x380dae49, 0x23582b11, 0x0cbd3a61, 0x02fcfaca, 0x2ae7f13d, 0x2c73c1cf, 0x0a246f75, 0xbb69}}}, + /* 13*16^63*G: */ + {{{0x0e36cb44, 0x3c6543bc, 0x1ca20191, 0x1fa2db23, 0x03357d61, 0x163f4362, 0x3aaa8bc0, 0x158d34e3, 0x1551}}, + {{0x1f495a68, 0x0a6bd194, 0x020c1e53, 0x30dc5d7c, 0x23205da8, 0x038fc2d1, 0x35215e37, 0x3ff1d555, 0xab4f}}}, + /* 15*16^63*G: */ + {{{0x3427bacc, 0x07e51841, 0x12d62e15, 0x1ccc5937, 0x0dc4aa9e, 0x163ac256, 0x35201363, 0x2f1911af, 0x3bc6}}, + {{0x2ad6fda6, 0x130cff57, 0x28beb471, 0x06dd6948, 0x16c02bd7, 0x18bb889b, 0x2c305cdb, 0x17301c5d, 0x8e30}}} + }, diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.c new file mode 100644 index 0000000..39c1aac --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.c @@ -0,0 +1,1283 @@ +/** + * Copyright (c) 2000-2001 Aaron D. Gifford + * Copyright (c) 2013-2014 Pavol Rusnak + * 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. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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. + */ + +#include +#include +#include "sha2.h" +#include "memzero.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including (which in turn includes + * where the appropriate definitions are actually + * made). + */ + +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +typedef uint8_t sha2_byte; /* Exactly 1 byte */ +typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +typedef uint64_t sha2_word64; /* Exactly 8 bytes */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA1_SHORT_BLOCK_LENGTH (SHA1_BLOCK_LENGTH - 8) +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: In the original SHA-256/384/512 document, the shift-right + * function was named R and the rotate-right function was called S. + * (See: http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf on the + * web.) + * + * The newer NIST FIPS 180-2 document uses a much clearer naming + * scheme, SHR for shift-right, ROTR for rotate-right, and ROTL for + * rotate-left. (See: + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + * on the web.) + * + * WARNING: These macros must be used cautiously, since they reference + * supplied parameters sometimes more than once, and thus could have + * unexpected side-effects if used without taking this into account. + */ + +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define SHR(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define ROTR32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define ROTR64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) +/* 32-bit Rotate-left (used in SHA-1): */ +#define ROTL32(b,x) (((x) << (b)) | ((x) >> (32 - (b)))) + +/* Two of six logical functions used in SHA-1, SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Function used in SHA-1: */ +#define Parity(x,y,z) ((x) ^ (y) ^ (z)) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (ROTR32(2, (x)) ^ ROTR32(13, (x)) ^ ROTR32(22, (x))) +#define Sigma1_256(x) (ROTR32(6, (x)) ^ ROTR32(11, (x)) ^ ROTR32(25, (x))) +#define sigma0_256(x) (ROTR32(7, (x)) ^ ROTR32(18, (x)) ^ SHR(3 , (x))) +#define sigma1_256(x) (ROTR32(17, (x)) ^ ROTR32(19, (x)) ^ SHR(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (ROTR64(28, (x)) ^ ROTR64(34, (x)) ^ ROTR64(39, (x))) +#define Sigma1_512(x) (ROTR64(14, (x)) ^ ROTR64(18, (x)) ^ ROTR64(41, (x))) +#define sigma0_512(x) (ROTR64( 1, (x)) ^ ROTR64( 8, (x)) ^ SHR( 7, (x))) +#define sigma1_512(x) (ROTR64(19, (x)) ^ ROTR64(61, (x)) ^ SHR( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +static void sha512_Last(SHA512_CTX*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ + +/* Hash constant words K for SHA-1: */ +#define K1_0_TO_19 0x5a827999UL +#define K1_20_TO_39 0x6ed9eba1UL +#define K1_40_TO_59 0x8f1bbcdcUL +#define K1_60_TO_79 0xca62c1d6UL + +/* Initial hash value H for SHA-1: */ +const sha2_word32 sha1_initial_hash_value[SHA1_DIGEST_LENGTH / sizeof(sha2_word32)] = { + 0x67452301UL, + 0xefcdab89UL, + 0x98badcfeUL, + 0x10325476UL, + 0xc3d2e1f0UL +}; + +/* Hash constant words K for SHA-256: */ +static const sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +static const sha2_word64 K512[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 +}; + +/* Initial hash value H for SHA-512 */ +const sha2_word64 sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + + +/*** SHA-1: ***********************************************************/ +void sha1_Init(SHA1_CTX* context) { + MEMCPY_BCOPY(context->state, sha1_initial_hash_value, SHA1_DIGEST_LENGTH); + memzero(context->buffer, SHA1_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-1 round macros: */ + +#define ROUND1_0_TO_15(a,b,c,d,e) \ + (e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \ + K1_0_TO_19 + ( W1[j] = *data++ ); \ + (b) = ROTL32(30, (b)); \ + j++; + +#define ROUND1_16_TO_19(a,b,c,d,e) \ + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ + (e) = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ + (b) = ROTL32(30, b); \ + j++; + +#define ROUND1_20_TO_39(a,b,c,d,e) \ + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ + (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ + (b) = ROTL32(30, b); \ + j++; + +#define ROUND1_40_TO_59(a,b,c,d,e) \ + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ + (e) = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ + (b) = ROTL32(30, b); \ + j++; + +#define ROUND1_60_TO_79(a,b,c,d,e) \ + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \ + (e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + ( W1[j&0x0f] = ROTL32(1, T1) ); \ + (b) = ROTL32(30, b); \ + j++; + +void sha1_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) { + sha2_word32 a, b, c, d, e; + sha2_word32 T1; + sha2_word32 W1[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + + j = 0; + + /* Rounds 0 to 15 unrolled: */ + ROUND1_0_TO_15(a,b,c,d,e); + ROUND1_0_TO_15(e,a,b,c,d); + ROUND1_0_TO_15(d,e,a,b,c); + ROUND1_0_TO_15(c,d,e,a,b); + ROUND1_0_TO_15(b,c,d,e,a); + ROUND1_0_TO_15(a,b,c,d,e); + ROUND1_0_TO_15(e,a,b,c,d); + ROUND1_0_TO_15(d,e,a,b,c); + ROUND1_0_TO_15(c,d,e,a,b); + ROUND1_0_TO_15(b,c,d,e,a); + ROUND1_0_TO_15(a,b,c,d,e); + ROUND1_0_TO_15(e,a,b,c,d); + ROUND1_0_TO_15(d,e,a,b,c); + ROUND1_0_TO_15(c,d,e,a,b); + ROUND1_0_TO_15(b,c,d,e,a); + ROUND1_0_TO_15(a,b,c,d,e); + + /* Rounds 16 to 19 unrolled: */ + ROUND1_16_TO_19(e,a,b,c,d); + ROUND1_16_TO_19(d,e,a,b,c); + ROUND1_16_TO_19(c,d,e,a,b); + ROUND1_16_TO_19(b,c,d,e,a); + + /* Rounds 20 to 39 unrolled: */ + ROUND1_20_TO_39(a,b,c,d,e); + ROUND1_20_TO_39(e,a,b,c,d); + ROUND1_20_TO_39(d,e,a,b,c); + ROUND1_20_TO_39(c,d,e,a,b); + ROUND1_20_TO_39(b,c,d,e,a); + ROUND1_20_TO_39(a,b,c,d,e); + ROUND1_20_TO_39(e,a,b,c,d); + ROUND1_20_TO_39(d,e,a,b,c); + ROUND1_20_TO_39(c,d,e,a,b); + ROUND1_20_TO_39(b,c,d,e,a); + ROUND1_20_TO_39(a,b,c,d,e); + ROUND1_20_TO_39(e,a,b,c,d); + ROUND1_20_TO_39(d,e,a,b,c); + ROUND1_20_TO_39(c,d,e,a,b); + ROUND1_20_TO_39(b,c,d,e,a); + ROUND1_20_TO_39(a,b,c,d,e); + ROUND1_20_TO_39(e,a,b,c,d); + ROUND1_20_TO_39(d,e,a,b,c); + ROUND1_20_TO_39(c,d,e,a,b); + ROUND1_20_TO_39(b,c,d,e,a); + + /* Rounds 40 to 59 unrolled: */ + ROUND1_40_TO_59(a,b,c,d,e); + ROUND1_40_TO_59(e,a,b,c,d); + ROUND1_40_TO_59(d,e,a,b,c); + ROUND1_40_TO_59(c,d,e,a,b); + ROUND1_40_TO_59(b,c,d,e,a); + ROUND1_40_TO_59(a,b,c,d,e); + ROUND1_40_TO_59(e,a,b,c,d); + ROUND1_40_TO_59(d,e,a,b,c); + ROUND1_40_TO_59(c,d,e,a,b); + ROUND1_40_TO_59(b,c,d,e,a); + ROUND1_40_TO_59(a,b,c,d,e); + ROUND1_40_TO_59(e,a,b,c,d); + ROUND1_40_TO_59(d,e,a,b,c); + ROUND1_40_TO_59(c,d,e,a,b); + ROUND1_40_TO_59(b,c,d,e,a); + ROUND1_40_TO_59(a,b,c,d,e); + ROUND1_40_TO_59(e,a,b,c,d); + ROUND1_40_TO_59(d,e,a,b,c); + ROUND1_40_TO_59(c,d,e,a,b); + ROUND1_40_TO_59(b,c,d,e,a); + + /* Rounds 60 to 79 unrolled: */ + ROUND1_60_TO_79(a,b,c,d,e); + ROUND1_60_TO_79(e,a,b,c,d); + ROUND1_60_TO_79(d,e,a,b,c); + ROUND1_60_TO_79(c,d,e,a,b); + ROUND1_60_TO_79(b,c,d,e,a); + ROUND1_60_TO_79(a,b,c,d,e); + ROUND1_60_TO_79(e,a,b,c,d); + ROUND1_60_TO_79(d,e,a,b,c); + ROUND1_60_TO_79(c,d,e,a,b); + ROUND1_60_TO_79(b,c,d,e,a); + ROUND1_60_TO_79(a,b,c,d,e); + ROUND1_60_TO_79(e,a,b,c,d); + ROUND1_60_TO_79(d,e,a,b,c); + ROUND1_60_TO_79(c,d,e,a,b); + ROUND1_60_TO_79(b,c,d,e,a); + ROUND1_60_TO_79(a,b,c,d,e); + ROUND1_60_TO_79(e,a,b,c,d); + ROUND1_60_TO_79(d,e,a,b,c); + ROUND1_60_TO_79(c,d,e,a,b); + ROUND1_60_TO_79(b,c,d,e,a); + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + + /* Clean up */ + a = b = c = d = e = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void sha1_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) { + sha2_word32 a, b, c, d, e; + sha2_word32 T1; + sha2_word32 W1[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + j = 0; + do { + T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + (W1[j] = *data++); + e = d; + d = c; + c = ROTL32(30, b); + b = a; + a = T1; + j++; + } while (j < 16); + + do { + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; + T1 = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + (W1[j&0x0f] = ROTL32(1, T1)); + e = d; + d = c; + c = ROTL32(30, b); + b = a; + a = T1; + j++; + } while (j < 20); + + do { + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; + T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + (W1[j&0x0f] = ROTL32(1, T1)); + e = d; + d = c; + c = ROTL32(30, b); + b = a; + a = T1; + j++; + } while (j < 40); + + do { + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; + T1 = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + (W1[j&0x0f] = ROTL32(1, T1)); + e = d; + d = c; + c = ROTL32(30, b); + b = a; + a = T1; + j++; + } while (j < 60); + + do { + T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; + T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + (W1[j&0x0f] = ROTL32(1, T1)); + e = d; + d = c; + c = ROTL32(30, b); + b = a; + a = T1; + j++; + } while (j < 80); + + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + + /* Clean up */ + a = b = c = d = e = T1 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void sha1_Update(SHA1_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + usedspace = (context->bitcount >> 3) % SHA1_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA1_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + sha1_Transform(context->state, context->buffer, context->state); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA1_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + MEMCPY_BCOPY(context->buffer, data, SHA1_BLOCK_LENGTH); +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + sha1_Transform(context->state, context->buffer, context->state); + context->bitcount += SHA1_BLOCK_LENGTH << 3; + len -= SHA1_BLOCK_LENGTH; + data += SHA1_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void sha1_Final(SHA1_CTX* context, sha2_byte digest[]) { + unsigned int usedspace; + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA1_BLOCK_LENGTH; + /* Begin padding with a 1 bit: */ + ((uint8_t*)context->buffer)[usedspace++] = 0x80; + + if (usedspace > SHA1_SHORT_BLOCK_LENGTH) { + memzero(((uint8_t*)context->buffer) + usedspace, SHA1_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + /* Do second-to-last transform: */ + sha1_Transform(context->state, context->buffer, context->state); + + /* And prepare the last transform: */ + usedspace = 0; + } + /* Set-up for the last transform: */ + memzero(((uint8_t*)context->buffer) + usedspace, SHA1_SHORT_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 14; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + /* Set the bit count: */ + context->buffer[14] = context->bitcount >> 32; + context->buffer[15] = context->bitcount & 0xffffffff; + + /* Final transform: */ + sha1_Transform(context->state, context->buffer, context->state); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + for (int j = 0; j < 5; j++) { + REVERSE32(context->state[j],context->state[j]); + } +#endif + MEMCPY_BCOPY(digest, context->state, SHA1_DIGEST_LENGTH); + } + + /* Clean up state data: */ + memzero(context, sizeof(SHA1_CTX)); + usedspace = 0; +} + +char *sha1_End(SHA1_CTX* context, char buffer[]) { + sha2_byte digest[SHA1_DIGEST_LENGTH], *d = digest; + int i; + + if (buffer != (char*)0) { + sha1_Final(context, digest); + + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + memzero(context, sizeof(SHA1_CTX)); + } + memzero(digest, SHA1_DIGEST_LENGTH); + return buffer; +} + +void sha1_Raw(const sha2_byte* data, size_t len, uint8_t digest[SHA1_DIGEST_LENGTH]) { + SHA1_CTX context; + sha1_Init(&context); + sha1_Update(&context, data, len); + sha1_Final(&context, digest); +} + +char* sha1_Data(const sha2_byte* data, size_t len, char digest[SHA1_DIGEST_STRING_LENGTH]) { + SHA1_CTX context; + + sha1_Init(&context); + sha1_Update(&context, data, len); + return sha1_End(&context, digest); +} + +/*** SHA-256: *********************************************************/ +void sha256_Init(SHA256_CTX* context) { + if (context == (SHA256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + memzero(context->buffer, SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1; + sha2_word32 W256[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + f = state_in[5]; + g = state_in[6]; + h = state_in[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + state_out[5] = state_in[5] + f; + state_out[6] = state_in[6] + g; + state_out[7] = state_in[7] + h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, W256[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + f = state_in[5]; + g = state_in[6]; + h = state_in[7]; + + j = 0; + do { + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + state_out[5] = state_in[5] + f; + state_out[6] = state_in[6] + g; + state_out[7] = state_in[7] + h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void sha256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + sha256_Transform(context->state, context->buffer, context->state); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + MEMCPY_BCOPY(context->buffer, data, SHA256_BLOCK_LENGTH); +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + sha256_Transform(context->state, context->buffer, context->state); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void sha256_Final(SHA256_CTX* context, sha2_byte digest[]) { + unsigned int usedspace; + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + /* Begin padding with a 1 bit: */ + ((uint8_t*)context->buffer)[usedspace++] = 0x80; + + if (usedspace > SHA256_SHORT_BLOCK_LENGTH) { + memzero(((uint8_t*)context->buffer) + usedspace, SHA256_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + /* Do second-to-last transform: */ + sha256_Transform(context->state, context->buffer, context->state); + + /* And prepare the last transform: */ + usedspace = 0; + } + /* Set-up for the last transform: */ + memzero(((uint8_t*)context->buffer) + usedspace, SHA256_SHORT_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 14; j++) { + REVERSE32(context->buffer[j],context->buffer[j]); + } +#endif + /* Set the bit count: */ + context->buffer[14] = context->bitcount >> 32; + context->buffer[15] = context->bitcount & 0xffffffff; + + /* Final transform: */ + sha256_Transform(context->state, context->buffer, context->state); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + for (int j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + } +#endif + MEMCPY_BCOPY(digest, context->state, SHA256_DIGEST_LENGTH); + } + + /* Clean up state data: */ + memzero(context, sizeof(SHA256_CTX)); + usedspace = 0; +} + +char *sha256_End(SHA256_CTX* context, char buffer[]) { + sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; + int i; + + if (buffer != (char*)0) { + sha256_Final(context, digest); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + memzero(context, sizeof(SHA256_CTX)); + } + memzero(digest, SHA256_DIGEST_LENGTH); + return buffer; +} + +void sha256_Raw(const sha2_byte* data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH]) { + SHA256_CTX context; + sha256_Init(&context); + sha256_Update(&context, data, len); + sha256_Final(&context, digest); +} + +char* sha256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { + SHA256_CTX context; + + sha256_Init(&context); + sha256_Update(&context, data, len); + return sha256_End(&context, digest); +} + + +/*** SHA-512: *********************************************************/ +void sha512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + memzero(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, W512[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + f = state_in[5]; + g = state_in[6]; + h = state_in[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + state_out[5] = state_in[5] + f; + state_out[6] = state_in[6] + g; + state_out[7] = state_in[7] + h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, W512[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state_in[0]; + b = state_in[1]; + c = state_in[2]; + d = state_in[3]; + e = state_in[4]; + f = state_in[5]; + g = state_in[6]; + h = state_in[7]; + + j = 0; + do { + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + state_out[0] = state_in[0] + a; + state_out[1] = state_in[1] + b; + state_out[2] = state_in[2] + c; + state_out[3] = state_in[3] + d; + state_out[4] = state_in[4] + e; + state_out[5] = state_in[5] + f; + state_out[6] = state_in[6] + g; + state_out[7] = state_in[7] + h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void sha512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE64(context->buffer[j],context->buffer[j]); + } +#endif + sha512_Transform(context->state, context->buffer, context->state); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + MEMCPY_BCOPY(context->buffer, data, SHA512_BLOCK_LENGTH); +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE64(context->buffer[j],context->buffer[j]); + } +#endif + sha512_Transform(context->state, context->buffer, context->state); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +static void sha512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + /* Begin padding with a 1 bit: */ + ((uint8_t*)context->buffer)[usedspace++] = 0x80; + + if (usedspace > SHA512_SHORT_BLOCK_LENGTH) { + memzero(((uint8_t*)context->buffer) + usedspace, SHA512_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 16; j++) { + REVERSE64(context->buffer[j],context->buffer[j]); + } +#endif + /* Do second-to-last transform: */ + sha512_Transform(context->state, context->buffer, context->state); + + /* And prepare the last transform: */ + usedspace = 0; + } + /* Set-up for the last transform: */ + memzero(((uint8_t*)context->buffer) + usedspace, SHA512_SHORT_BLOCK_LENGTH - usedspace); + +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + for (int j = 0; j < 14; j++) { + REVERSE64(context->buffer[j],context->buffer[j]); + } +#endif + /* Store the length of input data (in bits): */ + context->buffer[14] = context->bitcount[1]; + context->buffer[15] = context->bitcount[0]; + + /* Final transform: */ + sha512_Transform(context->state, context->buffer, context->state); +} + +void sha512_Final(SHA512_CTX* context, sha2_byte digest[]) { + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + sha512_Last(context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + for (int j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + } +#endif + MEMCPY_BCOPY(digest, context->state, SHA512_DIGEST_LENGTH); + } + + /* Zero out state data */ + memzero(context, sizeof(SHA512_CTX)); +} + +char *sha512_End(SHA512_CTX* context, char buffer[]) { + sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; + int i; + + if (buffer != (char*)0) { + sha512_Final(context, digest); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + memzero(context, sizeof(SHA512_CTX)); + } + memzero(digest, SHA512_DIGEST_LENGTH); + return buffer; +} + +void sha512_Raw(const sha2_byte* data, size_t len, uint8_t digest[SHA512_DIGEST_LENGTH]) { + SHA512_CTX context; + sha512_Init(&context); + sha512_Update(&context, data, len); + sha512_Final(&context, digest); +} + +char* sha512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { + SHA512_CTX context; + + sha512_Init(&context); + sha512_Update(&context, data, len); + return sha512_End(&context, digest); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.h new file mode 100644 index 0000000..7f519c5 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha2.h @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2000-2001 Aaron D. Gifford + * Copyright (c) 2013-2014 Pavol Rusnak + * 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. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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. + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#include +#include + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + +typedef struct _SHA1_CTX { + uint32_t state[5]; + uint64_t bitcount; + uint32_t buffer[SHA1_BLOCK_LENGTH/sizeof(uint32_t)]; +} SHA1_CTX; +typedef struct _SHA256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + uint64_t state[8]; + uint64_t bitcount[2]; + uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; +} SHA512_CTX; + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w,x) { \ + uint32_t tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + uint64_t tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +extern const uint32_t sha256_initial_hash_value[8]; +extern const uint64_t sha512_initial_hash_value[8]; + +void sha1_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out); +void sha1_Init(SHA1_CTX *); +void sha1_Update(SHA1_CTX*, const uint8_t*, size_t); +void sha1_Final(SHA1_CTX*, uint8_t[SHA1_DIGEST_LENGTH]); +char* sha1_End(SHA1_CTX*, char[SHA1_DIGEST_STRING_LENGTH]); +void sha1_Raw(const uint8_t*, size_t, uint8_t[SHA1_DIGEST_LENGTH]); +char* sha1_Data(const uint8_t*, size_t, char[SHA1_DIGEST_STRING_LENGTH]); + +void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out); +void sha256_Init(SHA256_CTX *); +void sha256_Update(SHA256_CTX*, const uint8_t*, size_t); +void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]); +char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); +void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]); +char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); + +void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out); +void sha512_Init(SHA512_CTX*); +void sha512_Update(SHA512_CTX*, const uint8_t*, size_t); +void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]); +char* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); +void sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]); +char* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.c b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.c new file mode 100644 index 0000000..3ef9db8 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.c @@ -0,0 +1,397 @@ +/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program 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. Use this program at your own risk! + */ + +#include +#include + +#include "sha3.h" +#include "memzero.h" + +#define I64(x) x##LL +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define le2me_64(x) (x) +#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) +# define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) + +/* constants */ +#define NumberOfRounds 24 + +/* SHA3 (Keccak) constants for 24 rounds */ +static uint64_t keccak_round_constants[NumberOfRounds] = { + I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000), + I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009), + I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A), + I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003), + I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A), + I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008) +}; + +/* Initializing a sha3 context for given number of output bits */ +static void keccak_Init(SHA3_CTX *ctx, unsigned bits) +{ + /* NB: The Keccak capacity parameter = bits * 2 */ + unsigned rate = 1600 - bits * 2; + + memset(ctx, 0, sizeof(SHA3_CTX)); + ctx->block_size = rate / 8; + assert(rate <= 1600 && (rate % 64) == 0); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_224_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 224); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_256_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 256); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_384_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 384); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_512_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 512); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) +{ + unsigned int x; + uint64_t C[5], D[5]; + + for (x = 0; x < 5; x++) { + C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20]; + } + D[0] = ROTL64(C[1], 1) ^ C[4]; + D[1] = ROTL64(C[2], 1) ^ C[0]; + D[2] = ROTL64(C[3], 1) ^ C[1]; + D[3] = ROTL64(C[4], 1) ^ C[2]; + D[4] = ROTL64(C[0], 1) ^ C[3]; + + for (x = 0; x < 5; x++) { + A[x] ^= D[x]; + A[x + 5] ^= D[x]; + A[x + 10] ^= D[x]; + A[x + 15] ^= D[x]; + A[x + 20] ^= D[x]; + } +} + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) +{ + uint64_t A1; + A1 = A[1]; + A[ 1] = A[ 6]; + A[ 6] = A[ 9]; + A[ 9] = A[22]; + A[22] = A[14]; + A[14] = A[20]; + A[20] = A[ 2]; + A[ 2] = A[12]; + A[12] = A[13]; + A[13] = A[19]; + A[19] = A[23]; + A[23] = A[15]; + A[15] = A[ 4]; + A[ 4] = A[24]; + A[24] = A[21]; + A[21] = A[ 8]; + A[ 8] = A[16]; + A[16] = A[ 5]; + A[ 5] = A[ 3]; + A[ 3] = A[18]; + A[18] = A[17]; + A[17] = A[11]; + A[11] = A[ 7]; + A[ 7] = A[10]; + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) +{ + int i; + for (i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + +static void sha3_permutation(uint64_t *state) +{ + int round; + for (round = 0; round < NumberOfRounds; round++) + { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + state[ 1] = ROTL64(state[ 1], 1); + state[ 2] = ROTL64(state[ 2], 62); + state[ 3] = ROTL64(state[ 3], 28); + state[ 4] = ROTL64(state[ 4], 27); + state[ 5] = ROTL64(state[ 5], 36); + state[ 6] = ROTL64(state[ 6], 44); + state[ 7] = ROTL64(state[ 7], 6); + state[ 8] = ROTL64(state[ 8], 55); + state[ 9] = ROTL64(state[ 9], 20); + state[10] = ROTL64(state[10], 3); + state[11] = ROTL64(state[11], 10); + state[12] = ROTL64(state[12], 43); + state[13] = ROTL64(state[13], 25); + state[14] = ROTL64(state[14], 39); + state[15] = ROTL64(state[15], 41); + state[16] = ROTL64(state[16], 45); + state[17] = ROTL64(state[17], 15); + state[18] = ROTL64(state[18], 21); + state[19] = ROTL64(state[19], 8); + state[20] = ROTL64(state[20], 18); + state[21] = ROTL64(state[21], 2); + state[22] = ROTL64(state[22], 61); + state[23] = ROTL64(state[23], 56); + state[24] = ROTL64(state[24], 14); + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= keccak_round_constants[round]; + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size) +{ + /* expanded loop */ + hash[ 0] ^= le2me_64(block[ 0]); + hash[ 1] ^= le2me_64(block[ 1]); + hash[ 2] ^= le2me_64(block[ 2]); + hash[ 3] ^= le2me_64(block[ 3]); + hash[ 4] ^= le2me_64(block[ 4]); + hash[ 5] ^= le2me_64(block[ 5]); + hash[ 6] ^= le2me_64(block[ 6]); + hash[ 7] ^= le2me_64(block[ 7]); + hash[ 8] ^= le2me_64(block[ 8]); + /* if not sha3-512 */ + if (block_size > 72) { + hash[ 9] ^= le2me_64(block[ 9]); + hash[10] ^= le2me_64(block[10]); + hash[11] ^= le2me_64(block[11]); + hash[12] ^= le2me_64(block[12]); + /* if not sha3-384 */ + if (block_size > 104) { + hash[13] ^= le2me_64(block[13]); + hash[14] ^= le2me_64(block[14]); + hash[15] ^= le2me_64(block[15]); + hash[16] ^= le2me_64(block[16]); + /* if not sha3-256 */ + if (block_size > 136) { + hash[17] ^= le2me_64(block[17]); +#ifdef FULL_SHA3_FAMILY_SUPPORT + /* if not sha3-224 */ + if (block_size > 144) { + hash[18] ^= le2me_64(block[18]); + hash[19] ^= le2me_64(block[19]); + hash[20] ^= le2me_64(block[20]); + hash[21] ^= le2me_64(block[21]); + hash[22] ^= le2me_64(block[22]); + hash[23] ^= le2me_64(block[23]); + hash[24] ^= le2me_64(block[24]); + } +#endif + } + } + } + /* make a permutation of the hash */ + sha3_permutation(hash); +} + +#define SHA3_FINALIZED 0x80000000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size) +{ + size_t idx = (size_t)ctx->rest; + size_t block_size = (size_t)ctx->block_size; + + if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % block_size); + + /* fill partial block */ + if (idx) { + size_t left = block_size - idx; + memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + msg += left; + size -= left; + } + while (size >= block_size) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (uint64_t*)(void*)msg; + } else { + memcpy(ctx->message, msg, block_size); + aligned_message_block = ctx->message; + } + + sha3_process_block(ctx->hash, aligned_message_block, block_size); + msg += block_size; + size -= block_size; + } + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void sha3_Final(SHA3_CTX *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x06; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); + memzero(ctx, sizeof(SHA3_CTX)); +} + +#if USE_KECCAK +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void keccak_Final(SHA3_CTX *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); + memzero(ctx, sizeof(SHA3_CTX)); +} + +void keccak_256(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx; + keccak_256_Init(&ctx); + keccak_Update(&ctx, data, len); + keccak_Final(&ctx, digest); +} + +void keccak_512(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx; + keccak_512_Init(&ctx); + keccak_Update(&ctx, data, len); + keccak_Final(&ctx, digest); +} +#endif /* USE_KECCAK */ + +void sha3_256(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx; + sha3_256_Init(&ctx); + sha3_Update(&ctx, data, len); + sha3_Final(&ctx, digest); +} + +void sha3_512(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx; + sha3_512_Init(&ctx); + sha3_Update(&ctx, data, len); + sha3_Final(&ctx, digest); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.h new file mode 100644 index 0000000..367369d --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Trezor/sha3.h @@ -0,0 +1,89 @@ +/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program 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. Use this program at your own risk! + */ + +#ifndef __SHA3_H__ +#define __SHA3_H__ + +#include +#include "options.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha3_224_hash_size 28 +#define sha3_256_hash_size 32 +#define sha3_384_hash_size 48 +#define sha3_512_hash_size 64 +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +#define SHA3_224_BLOCK_LENGTH 144 +#define SHA3_256_BLOCK_LENGTH 136 +#define SHA3_384_BLOCK_LENGTH 104 +#define SHA3_512_BLOCK_LENGTH 72 + +#define SHA3_224_DIGEST_LENGTH sha3_224_hash_size +#define SHA3_256_DIGEST_LENGTH sha3_256_hash_size +#define SHA3_384_DIGEST_LENGTH sha3_384_hash_size +#define SHA3_512_DIGEST_LENGTH sha3_512_hash_size + +/** + * SHA3 Algorithm context. + */ +typedef struct SHA3_CTX +{ + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + unsigned rest; + /* size of a message block processed at once */ + unsigned block_size; +} SHA3_CTX; + +/* methods for calculating the hash function */ + +void sha3_224_Init(SHA3_CTX *ctx); +void sha3_256_Init(SHA3_CTX *ctx); +void sha3_384_Init(SHA3_CTX *ctx); +void sha3_512_Init(SHA3_CTX *ctx); +void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size); +void sha3_Final(SHA3_CTX *ctx, unsigned char* result); + +#if USE_KECCAK +#define keccak_224_Init sha3_224_Init +#define keccak_256_Init sha3_256_Init +#define keccak_384_Init sha3_384_Init +#define keccak_512_Init sha3_512_Init +#define keccak_Update sha3_Update +void keccak_Final(SHA3_CTX *ctx, unsigned char* result); +void keccak_256(const unsigned char* data, size_t len, unsigned char* digest); +void keccak_512(const unsigned char* data, size_t len, unsigned char* digest); +#endif + +void sha3_256(const unsigned char* data, size_t len, unsigned char* digest); +void sha3_512(const unsigned char* data, size_t len, unsigned char* digest); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* __SHA3_H__ */ diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.cpp new file mode 100644 index 0000000..04f6f55 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.cpp @@ -0,0 +1,280 @@ +#include "UdpBridge.h" +#include "Web3.h" +#include "Util.h" +#include "KeyID.h" + +//Bridge defaults - override these with setupConnection +static const char *defaultServername = "james.lug.org.cn"; +static const uint16_t defaultPort = 5001; +static const uint16_t topPort = 5004; + +UdpBridge::UdpBridge() +{ + packetBuffer = new BYTE[256]; + currentReturnBytes = new BYTE[96]; + apiReturn = new APIReturn(); + serverName = std::string(defaultServername); + memset(sessionBytes, 0, 8); + port = defaultPort; + connectionState = handshake; + Serial.println("Starting UDP Bridge"); + initRandom = false; + pongCount = 0; +} + +void UdpBridge::setKey(KeyID *key, Web3 *w3) +{ + keyID = key; + web3 = w3; +} + +void UdpBridge::setupConnection(std::string& svName, uint16_t p) +{ + serverName = svName; + port = p; +} + +void UdpBridge::startConnection() +{ + //start default port and server + begin(port); +} + +void UdpBridge::checkClientAPI(BridgeCallback callback) +{ + maintainComms(); + parsePacket(); + int len = read(packetBuffer, 256); + + if (len > 0) + { + BYTE type = packetBuffer[0]; + int length = (packetBuffer[1] & 0xFF); + lastComms = millis(); + if (length > 0) + { + switch (type) + { + case 0: + if (isNewSession()) + { + memcpy(sessionBytes, packetBuffer + 2, 8); + if (!keyID->hasRecoveredKey()) + { + initRandomSeed(sessionBytes); + keyID->generatePrivateKey(web3); + } + else if (!initRandom) + { + initRandomSeed(sessionBytes); + Serial.println("Refresh random"); + initRandom = true; + } + + connectionState = have_token; + } + break; + case 1: + //we received a response to signature, should be a confirm session key + if (length == 8 && connectionValidCountdown == 0 && memcmp(sessionBytes, packetBuffer + 2, 8) == 0) + { + connectionState = confirmed; + connectionValidCountdown = 60; + memcpy(sessionBytes, packetBuffer + 2, 8); + memcpy(verifiedSessionBytes, packetBuffer + 2, 8); + } + break; + case 2: + //API call + if (packetBuffer[1] == currentQueryId) + { + //return the stored bytes + reSendResponse(); + } + else + { + currentQueryId = packetBuffer[1]; + int payloadLength = packetBuffer[2]; + scanAPI(packetBuffer + 3, apiReturn, payloadLength); + callback(apiReturn, this, currentQueryId); + } + break; + + case 3: //PONG + lastComms = millis(); + pongCount++; + break; + } + } + } +} + +void UdpBridge::scanAPI(const BYTE *packet, APIReturn *apiReturn, int payloadLength) +{ + apiReturn->clear(); + + int index = 0; + + //read length of API description + apiReturn->apiName = getArg(packet, index, payloadLength); + Serial.print("API: "); + Serial.println(apiReturn->apiName.c_str()); + + while (index < payloadLength) + { + std::string key = getArg(packet, index, payloadLength); + std::string param = getArg(packet, index, payloadLength); + apiReturn->params[key] = param; + Serial.print("PAIR: "); + Serial.print(key.c_str()); + Serial.print(" "); + Serial.println(param.c_str()); + } +} + +std::string UdpBridge::getArg(const BYTE *packet, int &index, int payloadLength) +{ + int argLen = packet[index++] & 0xFF; + std::string retVal = ""; + int endIndex = index + argLen; + if (endIndex > payloadLength) + endIndex = payloadLength; + for (; index < endIndex; index++) + { + retVal = retVal + (char)packet[index]; + } + + return retVal; +} + +void UdpBridge::reSendResponse() +{ + beginPacket(serverName.c_str(), port); + write(currentReturnBytes, currentReturnBytesLen); + endPacket(); +} + +void UdpBridge::sendRefreshRequest() +{ + packetBuffer[0] = 0x00; //fetch me a random + memcpy(packetBuffer + 1, sessionBytes, 8); + packetBuffer[9] = 0x01; + packetBuffer[10] = 0x00; + int packetLength = 11; + + beginPacket(serverName.c_str(), port); + write(packetBuffer, packetLength); + endPacket(); +} + +void UdpBridge::sendResponse(std::string resp, int methodId) +{ + packetBuffer[0] = 0x02; + //add session token + memcpy(packetBuffer + 1, verifiedSessionBytes, 8); + packetBuffer[9] = resp.length() + 1; + packetBuffer[10] = (BYTE)methodId; + memcpy(packetBuffer + 11, resp.c_str(), resp.length()); + + int packetLength = 11 + resp.length(); + + memcpy(currentReturnBytes, packetBuffer, packetLength); + currentReturnBytesLen = packetLength; + + beginPacket(serverName.c_str(), port); + write(packetBuffer, packetLength); + endPacket(); +} + +void UdpBridge::maintainComms() +{ + if (millis() > (lastCheck + 2000)) + { + lastCheck = millis(); + + switch (connectionState) + { + case handshake: + connectionValidCountdown = 0; + sendRefreshRequest(); + pongCount = 0; + break; + case have_token: + sendSignature(); + break; + case confirmed: + connectionValidCountdown--; + if (connectionValidCountdown <= 0) + { + connectionState = handshake; + memset(sessionBytes, 0, 8); + } + if ((connectionValidCountdown%2) == 0) + { + sendPing(); //send PING every 4 seconds + } + break; + } + + if (connectionState != handshake && millis() > (lastComms + 30*1000)) + { + connectionState = handshake; + memset(sessionBytes, 0, 8); + } + + if (millis() > lastComms + 180*1000) + { + lastComms = millis(); + //advance the port + port++; + if (port > topPort) + port = defaultPort; + begin(port); + } + } +} + +void UdpBridge::sendSignature() +{ + int packetLength = 0; + packetBuffer[0] = 0x01; + //write signature of session token + memcpy(packetBuffer + 1, sessionBytes, 8); + packetBuffer[9] = ETHERS_SIGNATURE_LENGTH; + keyID->getSignature(packetBuffer + 10, sessionBytes); + //add session token + packetLength = 10 + ETHERS_SIGNATURE_LENGTH; + + memcpy(currentReturnBytes, packetBuffer, packetLength); + currentReturnBytesLen = packetLength; + + beginPacket(serverName.c_str(), port); + write(packetBuffer, packetLength); + endPacket(); +} + +void UdpBridge::initRandomSeed(BYTE* randm) +{ + //generate array + uint32_t randBuffer[3]; + uint32_t *initKey = (uint32_t *) randm; + randBuffer[0] = initKey[0]; + randBuffer[1] = initKey[1]; + randBuffer[2] = micros(); + randomInitFromBuffer(randBuffer, 3); +} + +boolean UdpBridge::isNewSession() +{ + return (memcmp(sessionBytes, packetBuffer + 2, 8) != 0 && memcmp(sessionBytes, packetBuffer + 10, 8) == 0); +} + +void UdpBridge::sendPing() +{ + packetBuffer[0] = 0x03; //Ping + //write signature of session token + memcpy(packetBuffer + 1, verifiedSessionBytes, 8); + beginPacket(serverName.c_str(), port); + write(packetBuffer, 9); + endPacket(); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.h new file mode 100644 index 0000000..d4fde2c --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/UdpBridge.h @@ -0,0 +1,68 @@ +#ifndef UDP_BRIDGE_H +#define UDP_BRIDGE_H +#include +#include +#include +#include + +enum ConnectionStage +{ + handshake, + have_token, + confirmed +}; + +class UdpBridge; +//Format for API handler is void YourAPIHandler(APIReturn *apiReturn, UdpBridge *client, int methodId) { ... } +typedef void (*BridgeCallback)(APIReturn *, UdpBridge *, int methodId); + +class UdpBridge : public WiFiUDP +{ +public: + UdpBridge(); + void startConnection(); + void setKey(KeyID *keyId, Web3 *w3); + void checkClientAPI(BridgeCallback callback); + void setupConnection(std::string& serverName, uint16_t port); + void sendResponse(std::string resp, int methodId); + + int getConnectionStatus() { return connectionValidCountdown; } + int getConnectionPongs() { return (int) pongCount; } + int getPort() { return port; } + +private: + void scanAPI(const BYTE *packet, APIReturn *apiReturn, int payloadLength); + std::string getArg(const BYTE *packet, int &index, int payloadLength); + void closeConnection(); + void reSendResponse(); + void sendRefreshRequest(); + void maintainComms(); + void sendSignature(); + void initRandomSeed(BYTE* randm); + inline boolean isNewSession(); + void sendPing(); + + Web3 *web3; + KeyID *keyID; + APIReturn *apiReturn; + + BYTE *packetBuffer; + BYTE *currentReturnBytes; + int currentReturnBytesLen; + + BYTE sessionBytes[8]; + BYTE verifiedSessionBytes[8]; + BYTE *packetSendBuffer; + ConnectionStage connectionState; + long lastCheck = 0; + long lastComms = 0; + int connectionValidCountdown = 0; + BYTE currentQueryId; //ensure UDP packet gets through + BYTE pongCount = 0; + boolean initRandom; + + std::string serverName; + uint16_t port; +}; + +#endif \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.cpp new file mode 100644 index 0000000..2f40448 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.cpp @@ -0,0 +1,700 @@ +// Web3E Utilities +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#include +#include "Arduino.h" +#include +#include +#include +#include "TagReader/TagReader.h" + +static const char * _web3e_hexStr = "0123456789ABCDEF"; +// returns output (header) length +uint32_t Util::RlpEncodeWholeHeader(uint8_t* header_output, uint32_t total_len) { + if (total_len < 55) { + header_output[0] = (uint8_t)0xc0 + (uint8_t)total_len; + return 1; + } else { + uint8_t tmp_header[8]; + memset(tmp_header, 0, 8); + uint32_t hexdigit = 1; + uint32_t tmp = total_len; + while ((uint32_t)(tmp / 256) > 0) { + tmp_header[hexdigit] = (uint8_t)(tmp % 256); + tmp = (uint32_t)(tmp / 256); + hexdigit++; + } + tmp_header[hexdigit] = (uint8_t)(tmp); + tmp_header[0] = (uint8_t)0xf7 + (uint8_t)hexdigit; + + // fix direction for header + uint8_t header[8]; + memset(header, 0, 8); + header[0] = tmp_header[0]; + for (int i=0; i Util::RlpEncodeWholeHeaderWithVector(uint32_t total_len) { + vector header_output; + if (total_len < 55) { + header_output.push_back((uint8_t)0xc0 + (uint8_t)total_len); + } else { + vector tmp_header; + uint32_t hexdigit = 1; + uint32_t tmp = total_len; + while ((uint32_t)(tmp / 256) > 0) { + tmp_header.push_back((uint8_t)(tmp % 256)); + tmp = (uint32_t)(tmp / 256); + hexdigit++; + } + tmp_header.push_back((uint8_t)(tmp)); + tmp_header.insert(tmp_header.begin(), 0xf7 + (uint8_t)hexdigit); + + // fix direction for header + vector header; + header.push_back(tmp_header[0]); + for (int i=0; i 0) { + tmp_header[hexdigit] = (uint8_t)(tmp % 256); + tmp = (uint32_t)(tmp / 256); + hexdigit++; + } + tmp_header[hexdigit] = (uint8_t)(tmp); + tmp_header[0] = (uint8_t)0xb7 + (uint8_t)hexdigit; + + // fix direction for header + uint8_t header[8]; + memset(header, 0, 8); + header[0] = tmp_header[0]; + for (int i=0; i Util::RlpEncodeItemWithVector(const vector input) { + vector output; + uint16_t input_len = input.size(); + + if (input_len==1 && input[0] == 0x00) { + output.push_back(0x80); + } else if (input_len==1 && input[0] < 128) { + output.insert(output.end(), input.begin(), input.end()); + } else if (input_len <= 55) { + uint8_t _ = (uint8_t)0x80 + (uint8_t)input_len; + output.push_back(_); + output.insert(output.end(), input.begin(), input.end()); + } else { + vector tmp_header; + uint32_t tmp = input_len; + while ((uint32_t)(tmp / 256) > 0) { + tmp_header.push_back((uint8_t)(tmp % 256)); + tmp = (uint32_t)(tmp / 256); + } + tmp_header.push_back((uint8_t)(tmp)); + uint8_t len = tmp_header.size();// + 1; + tmp_header.insert(tmp_header.begin(), 0xb7 + len); + + // fix direction for header + vector header; + header.push_back(tmp_header[0]); + uint8_t hexdigit = tmp_header.size() - 1; + for (int i=0; i Util::ConvertNumberToVector(unsigned long long val) +{ + vector tmp; + vector ret; + if ((unsigned long long)(val / 256) >= 0) { + while ((unsigned long long)(val / 256) > 0) { + tmp.push_back((uint8_t)(val % 256)); + val = (unsigned long long)(val / 256); + } + tmp.push_back((uint8_t)(val % 256)); + uint8_t len = tmp.size(); + for (int i = 0; i Util::ConvertNumberToVector(uint32_t val) { + return ConvertNumberToVector((unsigned long long) val); +} + +uint32_t Util::ConvertNumberToUintArray(uint8_t *str, uint32_t val) { + uint32_t ret = 0; + uint8_t tmp[8]; + memset(tmp,0,8); + if ((uint32_t)(val / 256) >= 0) { + while ((uint32_t)(val / 256) > 0) { + tmp[ret] = (uint8_t)(val % 256); + val = (uint32_t)(val / 256); + ret++; + } + tmp[ret] = (uint8_t)(val % 256); + for (int i=0; i Util::ConvertHexToVector(const uint8_t *in) +{ + const uint8_t *ptr = in; + vector out; + if (ptr[0] == '0' && ptr[1] == 'x') ptr += 2; + + size_t lenstr = strlen((const char*)ptr); + int i = 0; + if ((lenstr % 2) == 1) //deal with odd sized hex strings + { + char c[2]; + c[0] = *ptr; + c[1] = 0; + out.push_back(ConvertCharToByte((const uint8_t*)c)); + i = 1; + } + for (; i Util::ConvertHexToVector(const string* str) { + return ConvertHexToVector((uint8_t*)(str->c_str())); +} + +uint32_t Util::ConvertCharStrToUintArray(uint8_t *out, const uint8_t *in) { + uint32_t ret = 0; + const uint8_t *ptr = in; + // remove "0x" + if (in[0] == '0' && in[1] == 'x') ptr += 2; + + size_t lenstr = strlen((const char*)ptr); + for (int i=0; i= '0' && s <= '9'){ + ret = uint8_t(s - '0'); + } else if(s >= 'a' && s <= 'f'){ + ret = uint8_t(s - 'a' + 10); + } else if(s >= 'A' && s <= 'F'){ + ret = uint8_t(s - 'A' + 10); + } + return ret; +} + +string Util::VectorToString(const vector *buf) +{ + return ConvertBytesToHex((const uint8_t*)buf->data(), buf->size()); +} + +string Util::ConvertIntegerToBytes(const int32_t value) +{ + size_t hex_len = 4 << 1; + std::string rc(hex_len, '0'); + for (size_t i = 0, j = (hex_len - 1) * 4; i> j) & 0x0f]; + } + return rc; +} + +string Util::PlainVectorToString(const vector *buf) +{ + char *buffer = (char*) alloca(buf->size() * 2 + 1); + char *pout = buffer; + for (int i = 0; i < buf->size(); i++) + { + *pout++ = _web3e_hexStr[((*buf)[i] >> 4) & 0xF]; + *pout++ = _web3e_hexStr[(*buf)[i] & 0xF]; + } + *pout = 0; + return string(buffer); +} + +string Util::ConvertBytesToHex(const uint8_t *bytes, int length) +{ + char *buffer = (char*)alloca(length * 2 + 3); + char *pout = buffer; + *pout++ = '0'; + *pout++ = 'x'; + for (int i = 0; i < length; i++) + { + *pout++ = _web3e_hexStr[((bytes)[i] >> 4) & 0xF]; + *pout++ = _web3e_hexStr[(bytes)[i] & 0xF]; + } + *pout = 0; + return std::string(buffer); +} + +void Util::ConvertHexToBytes(uint8_t *_dst, const char *_src, int length) +{ + if (_src[0] == '0' && _src[1] == 'x') _src += 2; //chop off 0x + + for (int i = 0; i < length; i++) + { + char a = _src[2 * i]; + char b = _src[2 * i + 1]; + byte extract = HexToInt(a) << 4 | HexToInt(b); + _dst[i] = extract; + } +} + +string Util::ConvertBase(int from, int to, const char *s) +{ + if (s == NULL) + return NULL; + + if (from < 2 || from > 36 || to < 2 || to > 36) { return NULL; } + + if (s[0] == '0' && s[1] == 'x') s += 2; + + int il = strlen(s); + + int *fs = new (alloca(sizeof(int)*il)) int[il]; + int k = 0; + int i, j; + + for (i = il - 1; i >= 0; i--) + { + if (s[i] >= '0' && s[i] <= '9') + { + fs[k] = (int)(s[i] - '0'); + } + else + { + if (s[i] >= 'A' && s[i] <= 'Z') + { + fs[k] = 10 + (int)(s[i] - 'A'); + } + else if (s[i] >= 'a' && s[i] <= 'z') + { + fs[k] = 10 + (int)(s[i] - 'a'); + } + else + { + return NULL; + } //only allow 0-9 A-Z characters + } + k++; + } + + for (i = 0; i= from) + return NULL; + } + + double x = ceil(log(from) / log(to)); + int ol = 1 + (il * x); + + int *ts = new (alloca(sizeof(int)*ol)) int[ol]; + int *cums = new (alloca(sizeof(int)*ol)) int[ol]; + + for (i = 0; i= ol) + { + if (rem > 0) + { + return NULL; + } + break; + } + cums[ip] += rem; + temp = cums[ip]; + } while (temp >= to); + } + + for (j = 0; j < ol; j++) + { + ts[j] = ts[j] * from; + } + + for (j = 0; j < ol; j++) //check for any remainders + { + int temp = ts[j]; + int rem = 0; + int ip = j; + do //fix up any remainders + { + rem = temp / to; + ts[ip] = temp - rem * to; + ip++; + if (ip >= ol) + { + if (rem > 0) + { + return NULL; + } + break; + } + ts[ip] += rem; + temp = ts[ip]; + } while (temp >= to); + } + } + + char *out = (char*)alloca(sizeof(char) * (ol + 1)); + + int spos = 0; + bool first = false; //leading zero flag + for (i = ol - 1; i >= 0; i--) + { + if (cums[i] != 0) + { + first = true; + } + if (!first) + { + continue; + } + + if (cums[i] < 10) + { + out[spos] = (char)(cums[i] + '0'); + } + else + { + out[spos] = (char)(cums[i] + 'A' - 10); + } + spos++; + } + out[spos] = 0; + return string(out); +} + +string Util::ConvertDecimal(int decimals, string *result) +{ + int decimalLocation = result->length() - decimals; + string newValue = ""; + if (decimalLocation <= 0) + { + newValue += "0."; + for (; decimalLocation < 0; decimalLocation++) + { + newValue += "0"; + } + newValue += *result; + } + else + { + //need to insert the point within the string + newValue = result->substr(0, decimalLocation); + newValue += "."; + newValue += result->substr(decimalLocation); + } + + return newValue; +} + +string Util::ConvertHexToASCII(const char *result, size_t length) +{ + //convert hex to string. + //first trim all the zeros + int index = 0; + string converted = ""; + char reader; + int state = 0; + bool endOfString = false; + + //No ASCII is less than 16 so this is safe + while (index < length && (result[index] == '0' || result[index] == 'x')) index++; + + while (index < length && endOfString == false) + { + // convert from hex to ascii + char c = result[index]; + switch (state) + { + case 0: + reader = (char)(Util::HexToInt(c) * 16); + state = 1; + break; + case 1: + reader += (char)Util::HexToInt(c); + if (reader == 0) + { + endOfString = true; + } + else + { + converted += reader; + state = 0; + } + break; + } + index++; + } + + return converted; +} + +/** + * Build a std::vector of bytes32 as hex strings + **/ +vector* Util::ConvertCharStrToVector32(const char *resultPtr, size_t resultSize, vector *result) +{ + if (resultSize < 64) return result; + if (resultPtr[0] == '0' && resultPtr[1] == 'x') resultPtr += 2; + //estimate size of return + int returnSize = resultSize / 64; + result->reserve(returnSize); + int index = 0; + char element[65]; + element[64] = 0; + + while (index <= (resultSize - 64)) + { + memcpy(element, resultPtr, 64); + result->push_back(string(element)); + resultPtr += 64; + index += 64; + } + + return result; +} + +string Util::InterpretStringResult(const char *result) +{ + //convert to vector bytes32 + string retVal = ""; + + if (result != NULL && strlen(result) > 0) + { + vector breakDown; + Util::ConvertCharStrToVector32(result, strlen(result), &breakDown); + + if (breakDown.size() > 2) + { + //check first value + auto itr = breakDown.begin(); + long dyn = strtol(itr++->c_str(), NULL, 16); + if (dyn == 32) //array marker + { + long length = strtol(itr++->c_str(), NULL, 16); + //now get a pointer to string immediately after the length marker + const char *strPtr = result + 2 + (2*64); + retVal = ConvertHexToASCII(strPtr, length*2); + } + } + } + + return retVal; +} + +vector *Util::InterpretVectorResult(string *result) +{ + vector *retVal = new vector(); + TagReader reader; + const char *value = reader.getTag(result, "result"); + + if (value != NULL && strlen(value) > 0) + { + vector breakDown; + Util::ConvertCharStrToVector32(value, reader.length(), &breakDown); + + if (breakDown.size() > 2) + { + //check first value + auto itr = breakDown.begin(); + long dyn = strtol(itr++->c_str(), NULL, 16); + if (dyn == 32) //array marker + { + long length = strtol(itr++->c_str(), NULL, 16); + + //checksum + if (breakDown.size() != (length + 2)) + { + Serial.println("Bad array result data."); + for (itr = breakDown.begin(); itr != breakDown.end(); itr++) Serial.println(*itr->c_str()); + } + for (;itr != breakDown.end(); itr++) + { + retVal->push_back(*itr); + } + } + } + } + + return retVal; +} + +void Util::PadForward(string *target, int targetSize) +{ + int remain = (targetSize*2) - (target->length() % targetSize); + char buffer[remain+1]; + memset(buffer, '0', remain); + buffer[remain] = 0; + *target = buffer + *target; +} + +uint256_t Util::ConvertToWei(double val, int decimals) +{ + char buffer[36]; //allow extra 4 chars for gcvt + if (val < 0) val = 0; + gcvt(val * pow(10.0, decimals), 32, buffer); + std::string weiStr = std::string(buffer); + std::size_t index = weiStr.find_last_of('.'); + if (index != std::string::npos) weiStr = weiStr.substr(0, index); + weiStr = ConvertBase(10, 16, weiStr.c_str()); + return uint256_t(weiStr.c_str()); +} + +string Util::ConvertWeiToEthString(uint256_t *weiVal, int decimals) +{ + char buffer[65]; + vector bytes = weiVal->export_bits_truncate(); + string hex = ConvertBytesToHex(bytes.data(), bytes.size()); + string amount = ConvertBase(16, 10, hex.c_str()); + int padLength = 0; + if (amount.length() < 64) + { + padLength = 64 - amount.length(); + memset(buffer, '0', padLength); + } + memcpy(buffer + padLength, amount.c_str(), amount.length()); + buffer[64] = 0; + + amount = string(buffer); + + //now place the decimal at the right spot + amount.insert(64 - decimals, "."); + + //crawl along from the other side to find the first character or the last zero + for (std::string::size_type i = 0; i < amount.size(); i++) { + if (amount[i] == '.') + { + amount = amount.substr(i - 1); + break; + } + else if (amount[i] != '0') + { + amount = amount.substr(i); + break; + } + } + + return amount; +} + +string Util::ConvertEthToWei(double eth) +{ + char buffer[36]; //allow extra 4 chars for gcvt + if (eth < 0) eth = 0; + gcvt(eth * pow(10.0, 18), 32, buffer); + std::string weiStr = std::string(buffer); + std::size_t index = weiStr.find_last_of('.'); + if (index != std::string::npos) weiStr = weiStr.substr(0, index); + return ConvertBase(10, 16, weiStr.c_str()); +} + +string Util::toString(int value) +{ + std::ostringstream oss; + oss << value; + return oss.str(); +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.h new file mode 100644 index 0000000..7a23d65 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Util.h @@ -0,0 +1,65 @@ +// Web3E Utilities +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#ifndef WEB3_UTIL_H +#define WEB3_UTIL_H + +#include +#include +#include +#include "uint256/uint256_t.h" + +using namespace std; + +class Util { +public: + // RLP implementation + // reference: + // https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP + static uint32_t RlpEncodeWholeHeader(uint8_t *header_output, uint32_t total_len); + static vector RlpEncodeWholeHeaderWithVector(uint32_t total_len); + static uint32_t RlpEncodeItem(uint8_t* output, const uint8_t* input, uint32_t input_len); + static vector RlpEncodeItemWithVector(const vector input); + + static uint32_t ConvertNumberToUintArray(uint8_t *str, uint32_t val); + static vector ConvertNumberToVector(uint32_t val); + static vector ConvertNumberToVector(unsigned long long val); + static uint32_t ConvertCharStrToUintArray(uint8_t *out, const uint8_t *in); + static vector ConvertHexToVector(const uint8_t *in); + static vector ConvertHexToVector(const string* str); + static char * ConvertToString(const uint8_t *in); + + static uint8_t HexToInt(uint8_t s); + static string VectorToString(const vector *buf); + static string PlainVectorToString(const vector *buf); + static string ConvertBytesToHex(const uint8_t *bytes, int length); + static void ConvertHexToBytes(uint8_t *_dst, const char *_src, int length); + static string ConvertBase(int from, int to, const char *s); + static string ConvertDecimal(int decimal, string *s); + static string ConvertString(const char* value); + static string ConvertHexToASCII(const char *result, size_t length); + static string InterpretStringResult(const char *result); + static vector* InterpretVectorResult(string *result); + static void PadForward(string *target, int targetSize); + static uint256_t ConvertToWei(double val, int decimals); + static string ConvertWeiToEthString(uint256_t *weiVal, int decimals); + + static vector* ConvertCharStrToVector32(const char *resultPtr, size_t resultSize, vector *result); + + static string ConvertEthToWei(double eth); + static string toString(int value); + + static string ConvertIntegerToBytes(const int32_t value); + +private: + static uint8_t ConvertCharToByte(const uint8_t* ptr); + +}; + +#endif //WEB3_UTIL_H diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.cpp new file mode 100644 index 0000000..07d3799 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.cpp @@ -0,0 +1,321 @@ +// Web3E main header +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#include "Web3.h" +#include +#include "CaCert.h" +#include "Util.h" +#include "cJSON/cJSON.h" +#include +#include + +WiFiClientSecure client; +Web3::Web3(const char* _host, const char* _path) { + client.setCACert(infura_ca_cert); + host = _host; + path = _path; +} + +string Web3::Web3ClientVersion() { + string m = "web3_clientVersion"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getString(&output); +} + +string Web3::Web3Sha3(const string* data) { + string m = "web3_sha3"; + string p = "[\"" + *data + "\"]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getString(&output); +} + +int Web3::NetVersion() { + string m = "net_version"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getInt(&output); +} + +bool Web3::NetListening() { + string m = "net_listening"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getBool(&output); +} + +int Web3::NetPeerCount() { + string m = "net_peerCount"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getInt(&output); +} + +double Web3::EthProtocolVersion() { + string m = "eth_protocolVersion"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getDouble(&output); +} + +bool Web3::EthSyncing() { + string m = "eth_syncing"; + string p = "[]"; + string input = generateJson(&m, &p); + string result = exec(&input); + + cJSON *root, *value; + root = cJSON_Parse(result.c_str()); + value = cJSON_GetObjectItem(root, "result"); + bool ret; + if (cJSON_IsBool(value)) { + ret = false; + } else{ + ret = true; + } + cJSON_free(root); + return ret; +} + +bool Web3::EthMining() { + string m = "eth_mining"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getBool(&output); +} + +double Web3::EthHashrate() { + string m = "eth_hashrate"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getDouble(&output); +} + +long long int Web3::EthGasPrice() { + string m = "eth_gasPrice"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getLongLong(&output); +} + +void Web3::EthAccounts(char** array, int size) { + // TODO +} + +int Web3::EthBlockNumber() { + string m = "eth_blockNumber"; + string p = "[]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getInt(&output); +} + +uint256_t Web3::EthGetBalance(const string* address) { + string m = "eth_getBalance"; + string p = "[\"" + *address + "\",\"latest\"]"; + string input = generateJson(&m, &p); + string output = exec(&input); + return getUint256(&output); +} + +string Web3::EthViewCall(const string* data, const char* to) +{ + string m = "eth_call"; + string p = "[{\"data\":\"";// + *data; + p += data->c_str(); + p += "\",\"to\":\""; + p += to; + p += "\"}, \"latest\"]"; + string input = generateJson(&m, &p); + return exec(&input); +} + +int Web3::EthGetTransactionCount(const string* address) { + string m = "eth_getTransactionCount"; + string p = "[\"" + *address + "\",\"pending\"]"; //in case we need to push several transactions in a row + string input = generateJson(&m, &p); + string output = exec(&input); + return getInt(&output); +} + +string Web3::EthCall(const string* from, const char* to, long gas, long gasPrice, + const string* value, const string* data) { + // TODO use gas, gasprice and value + string m = "eth_call"; + string p = "[{\"from\":\"" + *from + "\",\"to\":\"" + + *to + "\",\"data\":\"" + *data + "\"}, \"latest\"]"; + string input = generateJson(&m, &p); + return exec(&input); +} + +string Web3::EthSendSignedTransaction(const string* data, const uint32_t dataLen) { + string m = "eth_sendRawTransaction"; + string p = "[\"" + *data + "\"]"; + string input = generateJson(&m, &p); +#if 0 + LOG(input); +#endif + return exec(&input); +} + +// ------------------------------- +// Private + +string Web3::generateJson(const string* method, const string* params) { + return "{\"jsonrpc\":\"2.0\",\"method\":\"" + *method + "\",\"params\":" + *params + ",\"id\":0}"; +} + +string Web3::exec(const string* data) { + string result; + + int connected = client.connect(host, 443); + if (!connected) { + Serial.print("Unable to connect to Host: "); + Serial.print(host); + return ""; + } + + // Make a HTTP request: + int l = data->size(); + stringstream ss; + ss << l; + string lstr = ss.str(); + + string strPost = "POST " + string(path) + " HTTP/1.1"; + string strHost = "Host: " + string(host); + string strContentLen = "Content-Length: " + lstr; + + client.println(strPost.c_str()); + client.println(strHost.c_str()); + client.println("Content-Type: application/json"); + client.println(strContentLen.c_str()); + client.println("Connection: close"); + client.println(); + client.println(data->c_str()); + + while (client.connected()) + { + String line = client.readStringUntil('\n'); + if (line == "\r") { + break; + } + } + + // if there are incoming bytes available + // from the server, read them and print them: + while (client.available()) { + char c = client.read(); + result += c; + } + client.stop(); + + return result; +} + +int Web3::getInt(const string* json) { + int ret = -1; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsString(value)) { + ret = strtol(value->valuestring, nullptr, 16); + } + cJSON_free(root); + return ret; +} + +long Web3::getLong(const string* json) { + long ret = -1; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsString(value)) { + ret = strtol(value->valuestring, nullptr, 16); + } + cJSON_free(root); + return ret; +} + +long long int Web3::getLongLong(const string* json) { + long long int ret = -1; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsString(value)) { + ret = strtoll(value->valuestring, nullptr, 16); + } + cJSON_free(root); + return ret; +} + +uint256_t Web3::getUint256(const string* json) { + uint256_t ret = 0; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsString(value)) { + ret = uint256_t(value->valuestring); + } + cJSON_free(root); + return ret; +} + +double Web3::getDouble(const string* json) { + double ret = -1; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsString(value)) { + ret = strtof(value->valuestring, nullptr); + } + cJSON_free(root); + return ret; +} + +bool Web3::getBool(const string* json) { + bool ret = false; + cJSON *root, *value; + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (cJSON_IsBool(value)) { + ret = (bool)value->valueint; + } + cJSON_free(root); + return ret; +} + +string Web3::getString(const string *json) +{ + cJSON *root, *value; + if (json->find("result") >= 0) + { + root = cJSON_Parse(json->c_str()); + value = cJSON_GetObjectItem(root, "result"); + if (value != NULL && cJSON_IsString(value)) + { + cJSON_free(root); + return string(value->valuestring); + } + cJSON_free(root); + } + return string(""); +} +const char* Web3::getDAppCode() +{ + return ""; +} \ No newline at end of file diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.h new file mode 100644 index 0000000..008f401 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/Web3.h @@ -0,0 +1,79 @@ +// Web3E main header +// +// By James Brown Githubs: @JamesSmartCell @AlphaWallet +// Twitters: @TallyDigital @AlphaWallet +// +// Based on Web3 Arduino by Okada, Takahiro. +// +// + +#ifndef ARDUINO_WEB3_WEB3_H +#define ARDUINO_WEB3_WEB3_H + +typedef unsigned char BYTE; +#define ETHERS_PRIVATEKEY_LENGTH 32 +#define ETHERS_PUBLICKEY_LENGTH 64 +#define ETHERS_ADDRESS_LENGTH 20 +#define ETHERS_KECCAK256_LENGTH 32 +#define ETHERS_SIGNATURE_LENGTH 65 + +class Web3; +class Crypto; +class KeyID; + +#include "stdint.h" +#include "uint256/uint256_t.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class Web3 { +public: + Web3(const char* _host, const char* _path); + string Web3ClientVersion(); + string Web3Sha3(const string* data); + int NetVersion(); + bool NetListening(); + int NetPeerCount(); + double EthProtocolVersion(); + bool EthSyncing(); + bool EthMining(); + double EthHashrate(); + long long int EthGasPrice(); + void EthAccounts(char** array, int size); + int EthBlockNumber(); + uint256_t EthGetBalance(const string* address); + int EthGetTransactionCount(const string* address); + string EthViewCall(const string* data, const char* to); + + string EthCall(const string* from, const char* to, long gas, long gasPrice, const string* value, const string* data); + string EthSendSignedTransaction(const string* data, const uint32_t dataLen); + + static const char* getDAppCode(); + + long long int getLongLong(const string* json); + string getString(const string* json); + int getInt(const string* json); + uint256_t getUint256(const string* json); + +private: + string exec(const string* data); + string generateJson(const string* method, const string* params); + + long getLong(const string* json); + double getDouble(const string* json); + bool getBool(const string* json); + +private: + const char* host; + const char* path; +}; + +#endif //ARDUINO_WEB3_WEB3_H diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.cpp new file mode 100644 index 0000000..a3745fc --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.cpp @@ -0,0 +1,2909 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { + if (!cJSON_IsString(item)) { + return NULL; + } + + return item->valuestring; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 7) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test; + + if (output_buffer == NULL) + { + return false; + } + + /* This checks for NaN and Infinity */ + if ((d * 0) != 0) + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occured */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = strlen((const char*)value) + sizeof(""); + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +#define cjson_min(a, b) ((a < b) ? a : b) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((len < 0) || (buf == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buf; + p.length = (size_t)len; + p.offset = 0; + p.noalloc = true; + p.format = fmt; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* faile to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL)) + { + return false; + } + + child = array->child; + + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + } + else + { + /* append to the end */ + while (child->next) + { + child = child->next; + } + suffix_object(child, item); + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return; + } + + add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return; + } + + add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item->prev != NULL) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + add_item_to_array(array, newitem); + return; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (parent->child == item) + { + parent->child = replacement; + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return; + } + + cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + unsigned char *into = (unsigned char*)json; + + if (json == NULL) + { + return; + } + + while (*json) + { + if (*json == ' ') + { + json++; + } + else if (*json == '\t') + { + /* Whitespace characters. */ + json++; + } + else if (*json == '\r') + { + json++; + } + else if (*json=='\n') + { + json++; + } + else if ((*json == '/') && (json[1] == '/')) + { + /* double-slash comments, to end of line. */ + while (*json && (*json != '\n')) + { + json++; + } + } + else if ((*json == '/') && (json[1] == '*')) + { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) + { + json++; + } + json += 2; + } + else if (*json == '\"') + { + /* string literals, which are \" sensitive. */ + *into++ = (unsigned char)*json++; + while (*json && (*json != '\"')) + { + if (*json == '\\') + { + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + *into++ = (unsigned char)*json++; + } + else + { + /* All other characters. */ + *into++ = (unsigned char)*json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (a->valuedouble == b->valuedouble) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.h new file mode 100644 index 0000000..6e0bde9 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/cJSON/cJSON.h @@ -0,0 +1,277 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 7 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type __stdcall +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall +#endif +#else /* !WIN32 */ +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check if the item is a string and return its valuestring */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/arrray that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + + +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/platform-specific.inc b/Office Door/.pio/libdeps/esp32dev/Web3E/src/platform-specific.inc new file mode 100644 index 0000000..148cafc --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/platform-specific.inc @@ -0,0 +1,71 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_PLATFORM_SPECIFIC_H_ +#define _UECC_PLATFORM_SPECIFIC_H_ + +#include "types.h" + +#if (defined(_WIN32) || defined(_WIN64)) +/* Windows */ + +// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "advapi32.lib") + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static int default_RNG(uint8_t *dest, unsigned size) { + HCRYPTPROV prov; + if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + return 0; + } + + CryptGenRandom(prov, size, (BYTE *)dest); + CryptReleaseContext(prov, 0); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX) + +/* Some POSIX-like system with /dev/urandom or /dev/random. */ +#include +#include +#include + +#ifndef O_CLOEXEC + #define O_CLOEXEC 0 +#endif + +static int default_RNG(uint8_t *dest, unsigned size) { + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return 0; + } + } + + char *ptr = (char *)dest; + size_t left = size; + while (left > 0) { + ssize_t bytes_read = read(fd, ptr, left); + if (bytes_read <= 0) { // read failed + close(fd); + return 0; + } + left -= bytes_read; + ptr += bytes_read; + } + + close(fd); + return 1; +} +#define default_RNG_defined 1 + +#endif /* platform */ + +#endif /* _UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/types.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/types.h new file mode 100644 index 0000000..9307ee5 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/types.h @@ -0,0 +1,110 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_TYPES_H_ +#define _UECC_TYPES_H_ + +#include "UECC/uECC.h" + +#ifndef uECC_PLATFORM + #if __AVR__ + #define uECC_PLATFORM uECC_avr + #elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */ + #define uECC_PLATFORM uECC_arm_thumb2 + #elif defined(__thumb__) + #define uECC_PLATFORM uECC_arm_thumb + #elif defined(__arm__) || defined(_M_ARM) + #define uECC_PLATFORM uECC_arm + #elif defined(__aarch64__) + #define uECC_PLATFORM uECC_arm64 + #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__) + #define uECC_PLATFORM uECC_x86 + #elif defined(__amd64__) || defined(_M_X64) + #define uECC_PLATFORM uECC_x86_64 + #else + #define uECC_PLATFORM uECC_arch_other + #endif +#endif + +#ifndef uECC_ARM_USE_UMAAL + #if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6) + #define uECC_ARM_USE_UMAAL 1 + #elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__ + #define uECC_ARM_USE_UMAAL 1 + #else + #define uECC_ARM_USE_UMAAL 0 + #endif +#endif + +#ifndef uECC_WORD_SIZE + #if uECC_PLATFORM == uECC_avr + #define uECC_WORD_SIZE 1 + #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64) + #define uECC_WORD_SIZE 8 + #else + #define uECC_WORD_SIZE 4 + #endif +#endif + +#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8) + #error "Unsupported value for uECC_WORD_SIZE" +#endif + +#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1)) + #pragma message ("uECC_WORD_SIZE must be 1 for AVR") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 1 +#endif + +#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ + uECC_PLATFORM == uECC_arm_thumb2) && \ + (uECC_WORD_SIZE != 4)) + #pragma message ("uECC_WORD_SIZE must be 4 for ARM") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 4 +#endif + +#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302) + #define SUPPORTS_INT128 1 +#else + #define SUPPORTS_INT128 0 +#endif + +typedef int8_t wordcount_t; +typedef int16_t bitcount_t; +typedef int8_t cmpresult_t; + +#if (uECC_WORD_SIZE == 1) + +typedef uint8_t uECC_word_t; +typedef uint16_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80 +#define uECC_WORD_BITS 8 +#define uECC_WORD_BITS_SHIFT 3 +#define uECC_WORD_BITS_MASK 0x07 + +#elif (uECC_WORD_SIZE == 4) + +typedef uint32_t uECC_word_t; +typedef uint64_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 +#define uECC_WORD_BITS_SHIFT 5 +#define uECC_WORD_BITS_MASK 0x01F + +#elif (uECC_WORD_SIZE == 8) + +typedef uint64_t uECC_word_t; +#if SUPPORTS_INT128 +typedef unsigned __int128 uECC_dword_t; +#endif + +#define HIGH_BIT_SET 0x8000000000000000ull +#define uECC_WORD_BITS 64 +#define uECC_WORD_BITS_SHIFT 6 +#define uECC_WORD_BITS_MASK 0x03F + +#endif /* uECC_WORD_SIZE */ + +#endif /* _UECC_TYPES_H_ */ diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.build b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.build new file mode 100644 index 0000000..a548c6f --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.build @@ -0,0 +1,8 @@ +// IMPLEMENTATION BUILD HEADER +#ifndef _UINT256_T_BUILD + #define _UINT256_T_BUILD + #include "uint256_t_config.include" + #define UINT256_T_EXTERN _UINT256_T_EXPORT +#endif +#include "uint128_t.include" + diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.cpp new file mode 100644 index 0000000..de821f7 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.cpp @@ -0,0 +1,530 @@ +#include "uint128_t.build" + +const uint128_t uint128_0(0); +const uint128_t uint128_1(1); + +uint128_t::uint128_t() + : UPPER(0), LOWER(0) +{} + +uint128_t::uint128_t(const uint128_t & rhs) + : UPPER(rhs.UPPER), LOWER(rhs.LOWER) +{} + +uint128_t::uint128_t(uint128_t && rhs) + : UPPER(std::move(rhs.UPPER)), LOWER(std::move(rhs.LOWER)) +{ + if (this != &rhs){ + rhs.UPPER = 0; + rhs.LOWER = 0; + } +} + +uint128_t::uint128_t(std::string & s) { + init(s.c_str()); +} + +uint128_t::uint128_t(const char *s) { + init(s); +} + +void uint128_t::init(const char *s) { + if (s == NULL || s[0] == 0) { uint128_t(); return; } + if (s[1] == 'x') + s += 2; + else if (*s == 'x') + s++; + + UPPER = ConvertToUint64(s); + LOWER = ConvertToUint64(s + 16); +} + +uint64_t uint128_t::ConvertToUint64(const char *s) const { + int count = 0; + uint64_t val = 0; + uint8_t hv = HexToInt(s++); + while (hv != 0xFF && count < 16) { + val = (val << 4) | hv; + hv = HexToInt(&s[count]); + count++; + } + return val; +} + +uint8_t uint128_t::HexToInt(const char *s) const { + uint8_t ret = 0xFF; + if (*s >= '0' && *s <= '9') { + ret = uint8_t(*s - '0'); + } + else if (*s >= 'a' && *s <= 'f') { + ret = uint8_t(*s - 'a' + 10); + } + else if (*s >= 'A' && *s <= 'F') { + ret = uint8_t(*s - 'A' + 10); + } + return ret; +} + +uint128_t & uint128_t::operator=(const uint128_t & rhs){ + UPPER = rhs.UPPER; + LOWER = rhs.LOWER; + return *this; +} + +uint128_t & uint128_t::operator=(uint128_t && rhs){ + if (this != &rhs){ + UPPER = std::move(rhs.UPPER); + LOWER = std::move(rhs.LOWER); + rhs.UPPER = 0; + rhs.LOWER = 0; + } + return *this; +} + +uint128_t::operator bool() const{ + return (bool) (UPPER | LOWER); +} + +uint128_t::operator uint8_t() const{ + return (uint8_t) LOWER; +} + +uint128_t::operator uint16_t() const{ + return (uint16_t) LOWER; +} + +uint128_t::operator uint32_t() const{ + return (uint32_t) LOWER; +} + +uint128_t::operator uint64_t() const{ + return (uint64_t) LOWER; +} + +uint128_t uint128_t::operator&(const uint128_t & rhs) const{ + return uint128_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER); +} + +uint128_t & uint128_t::operator&=(const uint128_t & rhs){ + UPPER &= rhs.UPPER; + LOWER &= rhs.LOWER; + return *this; +} + +uint128_t uint128_t::operator|(const uint128_t & rhs) const{ + return uint128_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER); +} + +uint128_t & uint128_t::operator|=(const uint128_t & rhs){ + UPPER |= rhs.UPPER; + LOWER |= rhs.LOWER; + return *this; +} + +uint128_t uint128_t::operator^(const uint128_t & rhs) const{ + return uint128_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER); +} + +uint128_t & uint128_t::operator^=(const uint128_t & rhs){ + UPPER ^= rhs.UPPER; + LOWER ^= rhs.LOWER; + return *this; +} + +uint128_t uint128_t::operator~() const{ + return uint128_t(~UPPER, ~LOWER); +} + +uint128_t uint128_t::operator<<(const uint128_t & rhs) const{ + const uint64_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) || (shift >= 128)){ + return uint128_0; + } + else if (shift == 64){ + return uint128_t(LOWER, 0); + } + else if (shift == 0){ + return *this; + } + else if (shift < 64){ + return uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift); + } + else if ((128 > shift) && (shift > 64)){ + return uint128_t(LOWER << (shift - 64), 0); + } + else{ + return uint128_0; + } +} + +uint128_t & uint128_t::operator<<=(const uint128_t & rhs){ + *this = *this << rhs; + return *this; +} + +uint128_t uint128_t::operator>>(const uint128_t & rhs) const{ + const uint64_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) || (shift >= 128)){ + return uint128_0; + } + else if (shift == 64){ + return uint128_t(0, UPPER); + } + else if (shift == 0){ + return *this; + } + else if (shift < 64){ + return uint128_t(UPPER >> shift, (UPPER << (64 - shift)) + (LOWER >> shift)); + } + else if ((128 > shift) && (shift > 64)){ + return uint128_t(0, (UPPER >> (shift - 64))); + } + else{ + return uint128_0; + } +} + +uint128_t & uint128_t::operator>>=(const uint128_t & rhs){ + *this = *this >> rhs; + return *this; +} + +bool uint128_t::operator!() const{ + return !(bool) (UPPER | LOWER); +} + +bool uint128_t::operator&&(const uint128_t & rhs) const{ + return ((bool) *this && rhs); +} + +bool uint128_t::operator||(const uint128_t & rhs) const{ + return ((bool) *this || rhs); +} + +bool uint128_t::operator==(const uint128_t & rhs) const{ + return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER)); +} + +bool uint128_t::operator!=(const uint128_t & rhs) const{ + return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER)); +} + +bool uint128_t::operator>(const uint128_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER > rhs.LOWER); + } + return (UPPER > rhs.UPPER); +} + +bool uint128_t::operator<(const uint128_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER < rhs.LOWER); + } + return (UPPER < rhs.UPPER); +} + +bool uint128_t::operator>=(const uint128_t & rhs) const{ + return ((*this > rhs) | (*this == rhs)); +} + +bool uint128_t::operator<=(const uint128_t & rhs) const{ + return ((*this < rhs) | (*this == rhs)); +} + +uint128_t uint128_t::operator+(const uint128_t & rhs) const{ + return uint128_t(UPPER + rhs.UPPER + ((LOWER + rhs.LOWER) < LOWER), LOWER + rhs.LOWER); +} + +uint128_t & uint128_t::operator+=(const uint128_t & rhs){ + UPPER += rhs.UPPER + ((LOWER + rhs.LOWER) < LOWER); + LOWER += rhs.LOWER; + return *this; +} + +uint128_t uint128_t::operator-(const uint128_t & rhs) const{ + return uint128_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER); +} + +uint128_t & uint128_t::operator-=(const uint128_t & rhs){ + *this = *this - rhs; + return *this; +} + +uint128_t uint128_t::operator*(const uint128_t & rhs) const{ + // split values into 4 32-bit parts + uint64_t top[4] = {UPPER >> 32, UPPER & 0xffffffff, LOWER >> 32, LOWER & 0xffffffff}; + uint64_t bottom[4] = {rhs.UPPER >> 32, rhs.UPPER & 0xffffffff, rhs.LOWER >> 32, rhs.LOWER & 0xffffffff}; + uint64_t products[4][4]; + + // multiply each component of the values + for(int y = 3; y > -1; y--){ + for(int x = 3; x > -1; x--){ + products[3 - x][y] = top[x] * bottom[y]; + } + } + + // first row + uint64_t fourth32 = (products[0][3] & 0xffffffff); + uint64_t third32 = (products[0][2] & 0xffffffff) + (products[0][3] >> 32); + uint64_t second32 = (products[0][1] & 0xffffffff) + (products[0][2] >> 32); + uint64_t first32 = (products[0][0] & 0xffffffff) + (products[0][1] >> 32); + + // second row + third32 += (products[1][3] & 0xffffffff); + second32 += (products[1][2] & 0xffffffff) + (products[1][3] >> 32); + first32 += (products[1][1] & 0xffffffff) + (products[1][2] >> 32); + + // third row + second32 += (products[2][3] & 0xffffffff); + first32 += (products[2][2] & 0xffffffff) + (products[2][3] >> 32); + + // fourth row + first32 += (products[3][3] & 0xffffffff); + + // move carry to next digit + third32 += fourth32 >> 32; + second32 += third32 >> 32; + first32 += second32 >> 32; + + // remove carry from current digit + fourth32 &= 0xffffffff; + third32 &= 0xffffffff; + second32 &= 0xffffffff; + first32 &= 0xffffffff; + + // combine components + return uint128_t((first32 << 32) | second32, (third32 << 32) | fourth32); +} + +uint128_t & uint128_t::operator*=(const uint128_t & rhs){ + *this = *this * rhs; + return *this; +} + +void uint128_t::ConvertToVector(std::vector & ret, const uint64_t & val) const { + ret.push_back(static_cast(val >> 56)); + ret.push_back(static_cast(val >> 48)); + ret.push_back(static_cast(val >> 40)); + ret.push_back(static_cast(val >> 32)); + ret.push_back(static_cast(val >> 24)); + ret.push_back(static_cast(val >> 16)); + ret.push_back(static_cast(val >> 8)); + ret.push_back(static_cast(val)); +} + +void uint128_t::export_bits(std::vector &ret) const { + ConvertToVector(ret, const_cast(UPPER)); + ConvertToVector(ret, const_cast(LOWER)); +} + +std::pair uint128_t::divmod(const uint128_t & lhs, const uint128_t & rhs) const{ + // Save some calculations ///////////////////// + if (rhs == uint128_0){ + throw std::domain_error("Error: division or modulus by 0"); + } + else if (rhs == uint128_1){ + return std::pair (lhs, uint128_0); + } + else if (lhs == rhs){ + return std::pair (uint128_1, uint128_0); + } + else if ((lhs == uint128_0) || (lhs < rhs)){ + return std::pair (uint128_0, lhs); + } + + std::pair qr (uint128_0, uint128_0); + for(uint8_t x = lhs.bits(); x > 0; x--){ + qr.first <<= uint128_1; + qr.second <<= uint128_1; + + if ((lhs >> (x - 1U)) & 1){ + qr.second++; + } + + if (qr.second >= rhs){ + qr.second -= rhs; + qr.first++; + } + } + return qr; +} + +uint128_t uint128_t::operator/(const uint128_t & rhs) const{ + return divmod(*this, rhs).first; +} + +uint128_t & uint128_t::operator/=(const uint128_t & rhs){ + *this = *this / rhs; + return *this; +} + +uint128_t uint128_t::operator%(const uint128_t & rhs) const{ + return divmod(*this, rhs).second; +} + +uint128_t & uint128_t::operator%=(const uint128_t & rhs){ + *this = *this % rhs; + return *this; +} + +uint128_t & uint128_t::operator++(){ + return *this += uint128_1; +} + +uint128_t uint128_t::operator++(int){ + uint128_t temp(*this); + ++*this; + return temp; +} + +uint128_t & uint128_t::operator--(){ + return *this -= uint128_1; +} + +uint128_t uint128_t::operator--(int){ + uint128_t temp(*this); + --*this; + return temp; +} + +uint128_t uint128_t::operator+() const{ + return *this; +} + +uint128_t uint128_t::operator-() const{ + return ~*this + uint128_1; +} + +const uint64_t & uint128_t::upper() const{ + return UPPER; +} + +const uint64_t & uint128_t::lower() const{ + return LOWER; +} + +uint8_t uint128_t::bits() const{ + uint8_t out = 0; + if (UPPER){ + out = 64; + uint64_t up = UPPER; + while (up){ + up >>= 1; + out++; + } + } + else{ + uint64_t low = LOWER; + while (low){ + low >>= 1; + out++; + } + } + return out; +} + +std::string uint128_t::str(uint8_t base, const unsigned int & len) const{ + if ((base < 2) || (base > 16)){ + throw std::invalid_argument("Base must be in the range [2, 16]"); + } + std::string out = ""; + if (!(*this)){ + out = "0"; + } + else{ + std::pair qr(*this, uint128_0); + do{ + qr = divmod(qr.first, base); + out = "0123456789abcdef"[(uint8_t) qr.second] + out; + } while (qr.first); + } + if (out.size() < len){ + out = std::string(len - out.size(), '0') + out; + } + return out; +} + +uint128_t operator<<(const bool & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const uint8_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const uint16_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const uint32_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const uint64_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const int8_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const int16_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const int32_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator<<(const int64_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) << rhs; +} + +uint128_t operator>>(const bool & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const uint8_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const uint16_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const uint32_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const uint64_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const int8_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const int16_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const int32_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +uint128_t operator>>(const int64_t & lhs, const uint128_t & rhs){ + return uint128_t(lhs) >> rhs; +} + +std::ostream & operator<<(std::ostream & stream, const uint128_t & rhs){ + if (stream.flags() & stream.oct){ + stream << rhs.str(8); + } + else if (stream.flags() & stream.dec){ + stream << rhs.str(10); + } + else if (stream.flags() & stream.hex){ + stream << rhs.str(16); + } + return stream; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.h new file mode 100644 index 0000000..5f30e93 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.h @@ -0,0 +1,8 @@ +// PUBLIC IMPORT HEADER +#ifndef _UINT128_H_ +#define _UINT128_H_ +#include "uint256_t_config.include" +#define UINT256_T_EXTERN _UINT256_T_IMPORT +#include "uint128_t.include" +#endif + diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.include b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.include new file mode 100644 index 0000000..093a5e4 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.include @@ -0,0 +1,508 @@ +/* +uint128_t.h +An unsigned 128 bit integer type for C++ + +Copyright (c) 2013 - 2017 Jason Lee @ calccrypto at gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +With much help from Auston Sterling + +Thanks to Stefan Deigmüller for finding +a bug in operator*. + +Thanks to François Dessenne for convincing me +to do a general rewrite of this class. +*/ + +#ifndef __UINT128_T__ +#define __UINT128_T__ + +#include +#include +#include +#include +#include +#include +#include + +class UINT256_T_EXTERN uint128_t; + +// Give uint128_t type traits +namespace std { // This is probably not a good idea + template <> struct is_arithmetic : std::true_type {}; + template <> struct is_integral : std::true_type {}; + template <> struct is_unsigned : std::true_type {}; +}; + +class uint128_t{ + private: + uint64_t UPPER, LOWER; + + public: + // Constructors + uint128_t(); + uint128_t(const uint128_t & rhs); + uint128_t(uint128_t && rhs); + uint128_t(std::string & s); + uint128_t(const char *s); + + template ::value, T>::type > + uint128_t(const T & rhs) + : UPPER(0), LOWER(rhs) + {} + + template ::value && std::is_integral::value, void>::type> + uint128_t(const S & upper_rhs, const T & lower_rhs) + : UPPER(upper_rhs), LOWER(lower_rhs) + {} + + // RHS input args only + + // Assignment Operator + uint128_t & operator=(const uint128_t & rhs); + uint128_t & operator=(uint128_t && rhs); + + template ::value, T>::type > + uint128_t & operator=(const T & rhs){ + UPPER = 0; + LOWER = rhs; + return *this; + } + + // Typecast Operators + operator bool() const; + operator uint8_t() const; + operator uint16_t() const; + operator uint32_t() const; + operator uint64_t() const; + + // Bitwise Operators + uint128_t operator&(const uint128_t & rhs) const; + + void export_bits(std::vector & ret) const; + + template ::value, T>::type > + uint128_t operator&(const T & rhs) const{ + return uint128_t(0, LOWER & (uint64_t) rhs); + } + + uint128_t & operator&=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator&=(const T & rhs){ + UPPER = 0; + LOWER &= rhs; + return *this; + } + + uint128_t operator|(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator|(const T & rhs) const{ + return uint128_t(UPPER, LOWER | (uint64_t) rhs); + } + + uint128_t & operator|=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator|=(const T & rhs){ + LOWER |= (uint64_t) rhs; + return *this; + } + + uint128_t operator^(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator^(const T & rhs) const{ + return uint128_t(UPPER, LOWER ^ (uint64_t) rhs); + } + + uint128_t & operator^=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator^=(const T & rhs){ + LOWER ^= (uint64_t) rhs; + return *this; + } + + uint128_t operator~() const; + + // Bit Shift Operators + uint128_t operator<<(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator<<(const T & rhs) const{ + return *this << uint128_t(rhs); + } + + uint128_t & operator<<=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator<<=(const T & rhs){ + *this = *this << uint128_t(rhs); + return *this; + } + + uint128_t operator>>(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator>>(const T & rhs) const{ + return *this >> uint128_t(rhs); + } + + uint128_t & operator>>=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator>>=(const T & rhs){ + *this = *this >> uint128_t(rhs); + return *this; + } + + // Logical Operators + bool operator!() const; + bool operator&&(const uint128_t & rhs) const; + bool operator||(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator&&(const T & rhs){ + return static_cast (*this && rhs); + } + + template ::value, T>::type > + bool operator||(const T & rhs){ + return static_cast (*this || rhs); + } + + // Comparison Operators + bool operator==(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator==(const T & rhs) const{ + return (!UPPER && (LOWER == (uint64_t) rhs)); + } + + bool operator!=(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator!=(const T & rhs) const{ + return (UPPER | (LOWER != (uint64_t) rhs)); + } + + bool operator>(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator>(const T & rhs) const{ + return (UPPER || (LOWER > (uint64_t) rhs)); + } + + bool operator<(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator<(const T & rhs) const{ + return (!UPPER)?(LOWER < (uint64_t) rhs):false; + } + + bool operator>=(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator>=(const T & rhs) const{ + return ((*this > rhs) | (*this == rhs)); + } + + bool operator<=(const uint128_t & rhs) const; + + template ::value, T>::type > + bool operator<=(const T & rhs) const{ + return ((*this < rhs) | (*this == rhs)); + } + + // Arithmetic Operators + uint128_t operator+(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator+(const T & rhs) const{ + return uint128_t(UPPER + ((LOWER + (uint64_t) rhs) < LOWER), LOWER + (uint64_t) rhs); + } + + uint128_t & operator+=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator+=(const T & rhs){ + UPPER = UPPER + ((LOWER + rhs) < LOWER); + LOWER = LOWER + rhs; + return *this; + } + + uint128_t operator-(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator-(const T & rhs) const{ + return uint128_t((uint64_t) (UPPER - ((LOWER - rhs) > LOWER)), (uint64_t) (LOWER - rhs)); + } + + uint128_t & operator-=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator-=(const T & rhs){ + *this = *this - rhs; + return *this; + } + + uint128_t operator*(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator*(const T & rhs) const{ + return *this * uint128_t(rhs); + } + + uint128_t & operator*=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator*=(const T & rhs){ + *this = *this * uint128_t(rhs); + return *this; + } + + private: + std::pair divmod(const uint128_t & lhs, const uint128_t & rhs) const; + void init(const char * s); + void ConvertToVector(std::vector & current, const uint64_t & val) const; + uint8_t HexToInt(const char *s) const; + uint64_t ConvertToUint64(const char *s) const; + + public: + uint128_t operator/(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator/(const T & rhs) const{ + return *this / uint128_t(rhs); + } + + uint128_t & operator/=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator/=(const T & rhs){ + *this = *this / uint128_t(rhs); + return *this; + } + + uint128_t operator%(const uint128_t & rhs) const; + + template ::value, T>::type > + uint128_t operator%(const T & rhs) const{ + return *this % uint128_t(rhs); + } + + uint128_t & operator%=(const uint128_t & rhs); + + template ::value, T>::type > + uint128_t & operator%=(const T & rhs){ + *this = *this % uint128_t(rhs); + return *this; + } + + // Increment Operator + uint128_t & operator++(); + uint128_t operator++(int); + + // Decrement Operator + uint128_t & operator--(); + uint128_t operator--(int); + + // Nothing done since promotion doesn't work here + uint128_t operator+() const; + + // two's complement + uint128_t operator-() const; + + // Get private values + const uint64_t & upper() const; + const uint64_t & lower() const; + + // Get bitsize of value + uint8_t bits() const; + + // Get string representation of value + std::string str(uint8_t base = 10, const unsigned int & len = 0) const; +}; + +// useful values +UINT256_T_EXTERN extern const uint128_t uint128_0; +UINT256_T_EXTERN extern const uint128_t uint128_1; + +// lhs type T as first arguemnt +// If the output is not a bool, casts to type T + +// Bitwise Operators +template ::value, T>::type > +uint128_t operator&(const T & lhs, const uint128_t & rhs){ + return rhs & lhs; +} + +template ::value, T>::type > +T & operator&=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (rhs & lhs); +} + +template ::value, T>::type > +uint128_t operator|(const T & lhs, const uint128_t & rhs){ + return rhs | lhs; +} + +template ::value, T>::type > +T & operator|=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (rhs | lhs); +} + +template ::value, T>::type > +uint128_t operator^(const T & lhs, const uint128_t & rhs){ + return rhs ^ lhs; +} + +template ::value, T>::type > +T & operator^=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (rhs ^ lhs); +} + +// Bitshift operators +UINT256_T_EXTERN uint128_t operator<<(const bool & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const uint8_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const uint16_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const uint32_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const uint64_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const int8_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const int16_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const int32_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator<<(const int64_t & lhs, const uint128_t & rhs); + +template ::value, T>::type > +T & operator<<=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (uint128_t(lhs) << rhs); +} + +UINT256_T_EXTERN uint128_t operator>>(const bool & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const uint8_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const uint16_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const uint32_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const uint64_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const int8_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const int16_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const int32_t & lhs, const uint128_t & rhs); +UINT256_T_EXTERN uint128_t operator>>(const int64_t & lhs, const uint128_t & rhs); + +template ::value, T>::type > +T & operator>>=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (uint128_t(lhs) >> rhs); +} + +// Comparison Operators +template ::value, T>::type > +bool operator==(const T & lhs, const uint128_t & rhs){ + return (!rhs.upper() && ((uint64_t) lhs == rhs.lower())); +} + +template ::value, T>::type > +bool operator!=(const T & lhs, const uint128_t & rhs){ + return (rhs.upper() | ((uint64_t) lhs != rhs.lower())); +} + +template ::value, T>::type > +bool operator>(const T & lhs, const uint128_t & rhs){ + return (!rhs.upper()) && ((uint64_t) lhs > rhs.lower()); +} + +template ::value, T>::type > +bool operator<(const T & lhs, const uint128_t & rhs){ + if (rhs.upper()){ + return true; + } + return ((uint64_t) lhs < rhs.lower()); +} + +template ::value, T>::type > +bool operator>=(const T & lhs, const uint128_t & rhs){ + if (rhs.upper()){ + return false; + } + return ((uint64_t) lhs >= rhs.lower()); +} + +template ::value, T>::type > +bool operator<=(const T & lhs, const uint128_t & rhs){ + if (rhs.upper()){ + return true; + } + return ((uint64_t) lhs <= rhs.lower()); +} + +// Arithmetic Operators +template ::value, T>::type > +uint128_t operator+(const T & lhs, const uint128_t & rhs){ + return rhs + lhs; +} + +template ::value, T>::type > +T & operator+=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (rhs + lhs); +} + +template ::value, T>::type > +uint128_t operator-(const T & lhs, const uint128_t & rhs){ + return -(rhs - lhs); +} + +template ::value, T>::type > +T & operator-=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (-(rhs - lhs)); +} + +template ::value, T>::type > +uint128_t operator*(const T & lhs, const uint128_t & rhs){ + return rhs * lhs; +} + +template ::value, T>::type > +T & operator*=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (rhs * lhs); +} + +template ::value, T>::type > +uint128_t operator/(const T & lhs, const uint128_t & rhs){ + return uint128_t(lhs) / rhs; +} + +template ::value, T>::type > +T & operator/=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (uint128_t(lhs) / rhs); +} + +template ::value, T>::type > +uint128_t operator%(const T & lhs, const uint128_t & rhs){ + return uint128_t(lhs) % rhs; +} + +template ::value, T>::type > +T & operator%=(T & lhs, const uint128_t & rhs){ + return lhs = static_cast (uint128_t(lhs) % rhs); +} + +// IO Operator +UINT256_T_EXTERN std::ostream & operator<<(std::ostream & stream, const uint128_t & rhs); +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.build b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.build new file mode 100644 index 0000000..f458519 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.build @@ -0,0 +1,16 @@ +// IMPLEMENTATION BUILD HEADER + +// We need uint128_t symbols as plain "extern", neither import nor export +// because we're linking the 128 and 256 object files into a single library +// So we can only have one export for symbol in any translation unit +#define UINT256_T_EXTERN +#include "uint128_t.include" +#undef UINT256_T_EXTERN + +#ifndef _UNIT256_T_BUILD + #define _UINT256_T_BUILD + #include "uint256_t_config.include" + #define UINT256_T_EXTERN _UINT256_T_EXPORT +#endif +#include "uint256_t.include" + diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.cpp b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.cpp new file mode 100644 index 0000000..a5dce13 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.cpp @@ -0,0 +1,761 @@ +#include "uint256_t.build" +#include +#include + +const uint128_t uint128_64(64); +const uint128_t uint128_128(128); +const uint128_t uint128_256(256); +const uint256_t uint256_0(0); +const uint256_t uint256_1(1); +const uint256_t uint256_max(uint128_t((uint64_t) -1, (uint64_t) -1), uint128_t((uint64_t) -1, (uint64_t) -1)); + +uint256_t::uint256_t() + : UPPER(uint128_0), LOWER(uint128_0) +{} + +uint256_t::uint256_t(const uint256_t & rhs) + : UPPER(rhs.UPPER), LOWER(rhs.LOWER) +{} + +uint256_t::uint256_t(uint256_t && rhs) + : UPPER(std::move(rhs.UPPER)), LOWER(std::move(rhs.LOWER)) +{ + if (this != &rhs){ + rhs.UPPER = uint128_0; + rhs.LOWER = uint128_0; + } +} + +uint256_t::uint256_t(const std::string & s) { + init(s.c_str()); +} + +uint256_t::uint256_t(const char * s) { + init(s); +} + +void uint256_t::init(const char * s) { + //create from string + char buffer[64]; + if (s == NULL) { uint256_t(); return; } + if (s[1] == 'x') + s += 2; + else if (*s == 'x') + s++; + + int len = strlen(s); + int padLength = 0; + if (len < 64) { + padLength = 64 - len; + memset(buffer, '0', padLength); + } + + memcpy(buffer + padLength, s, len); + + UPPER = uint128_t(buffer); + LOWER = uint128_t(buffer + 32); +} + +uint256_t & uint256_t::operator=(const uint256_t & rhs){ + UPPER = rhs.UPPER; + LOWER = rhs.LOWER; + return *this; +} + +uint256_t & uint256_t::operator=(uint256_t && rhs){ + if (this != &rhs){ + UPPER = std::move(rhs.UPPER); + LOWER = std::move(rhs.LOWER); + rhs.UPPER = uint128_0; + rhs.LOWER = uint128_0; + } + return *this; +} + +uint256_t::operator bool() const{ + return (bool) (UPPER | LOWER); +} + +uint256_t::operator uint8_t() const{ + return (uint8_t) LOWER; +} + +uint256_t::operator uint16_t() const{ + return (uint16_t) LOWER; +} + +uint256_t::operator uint32_t() const{ + return (uint32_t) LOWER; +} + +uint256_t::operator uint64_t() const{ + return (uint64_t) LOWER; +} + +uint256_t::operator uint128_t() const{ + return LOWER; +} + +uint256_t uint256_t::operator&(const uint128_t & rhs) const{ + return uint256_t(uint128_0, LOWER & rhs); +} + +uint256_t uint256_t::operator&(const uint256_t & rhs) const{ + return uint256_t(UPPER & rhs.UPPER, LOWER & rhs.LOWER); +} + +uint256_t & uint256_t::operator&=(const uint128_t & rhs){ + UPPER = uint128_0; + LOWER &= rhs; + return *this; +} + +uint256_t & uint256_t::operator&=(const uint256_t & rhs){ + UPPER &= rhs.UPPER; + LOWER &= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator|(const uint128_t & rhs) const{ + return uint256_t(UPPER , LOWER | rhs); +} + +uint256_t uint256_t::operator|(const uint256_t & rhs) const{ + return uint256_t(UPPER | rhs.UPPER, LOWER | rhs.LOWER); +} + +uint256_t & uint256_t::operator|=(const uint128_t & rhs){ + LOWER |= rhs; + return *this; +} + +uint256_t & uint256_t::operator|=(const uint256_t & rhs){ + UPPER |= rhs.UPPER; + LOWER |= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator^(const uint128_t & rhs) const{ + return uint256_t(UPPER, LOWER ^ rhs); +} + +uint256_t uint256_t::operator^(const uint256_t & rhs) const{ + return uint256_t(UPPER ^ rhs.UPPER, LOWER ^ rhs.LOWER); +} + +uint256_t & uint256_t::operator^=(const uint128_t & rhs){ + LOWER ^= rhs; + return *this; +} + +uint256_t & uint256_t::operator^=(const uint256_t & rhs){ + UPPER ^= rhs.UPPER; + LOWER ^= rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator~() const{ + return uint256_t(~UPPER, ~LOWER); +} + +uint256_t uint256_t::operator<<(const uint128_t & rhs) const{ + return *this << uint256_t(rhs); +} + +uint256_t uint256_t::operator<<(const uint256_t & rhs) const{ + const uint128_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) || (shift >= uint128_256)){ + return uint256_0; + } + else if (shift == uint128_128){ + return uint256_t(LOWER, uint128_0); + } + else if (shift == uint128_0){ + return *this; + } + else if (shift < uint128_128){ + return uint256_t((UPPER << shift) + (LOWER >> (uint128_128 - shift)), LOWER << shift); + } + else if ((uint128_256 > shift) && (shift > uint128_128)){ + return uint256_t(LOWER << (shift - uint128_128), uint128_0); + } + else{ + return uint256_0; + } +} + +uint256_t & uint256_t::operator<<=(const uint128_t & shift){ + return *this <<= uint256_t(shift); +} + +uint256_t & uint256_t::operator<<=(const uint256_t & shift){ + *this = *this << shift; + return *this; +} + +uint256_t uint256_t::operator>>(const uint128_t & rhs) const{ + return *this >> uint256_t(rhs); +} + +uint256_t uint256_t::operator>>(const uint256_t & rhs) const{ + const uint128_t shift = rhs.LOWER; + if (((bool) rhs.UPPER) | (shift >= uint128_256)){ + return uint256_0; + } + else if (shift == uint128_128){ + return uint256_t(UPPER); + } + else if (shift == uint128_0){ + return *this; + } + else if (shift < uint128_128){ + return uint256_t(UPPER >> shift, (UPPER << (uint128_128 - shift)) + (LOWER >> shift)); + } + else if ((uint128_256 > shift) && (shift > uint128_128)){ + return uint256_t(UPPER >> (shift - uint128_128)); + } + else{ + return uint256_0; + } +} + +uint256_t & uint256_t::operator>>=(const uint128_t & shift){ + return *this >>= uint256_t(shift); +} + +uint256_t & uint256_t::operator>>=(const uint256_t & shift){ + *this = *this >> shift; + return *this; +} + +bool uint256_t::operator!() const{ + return ! (bool) *this; +} + +bool uint256_t::operator&&(const uint128_t & rhs) const{ + return (*this && uint256_t(rhs)); +} + +bool uint256_t::operator&&(const uint256_t & rhs) const{ + return ((bool) *this && (bool) rhs); +} + +bool uint256_t::operator||(const uint128_t & rhs) const{ + return (*this || uint256_t(rhs)); +} + +bool uint256_t::operator||(const uint256_t & rhs) const{ + return ((bool) *this || (bool) rhs); +} + +bool uint256_t::operator==(const uint128_t & rhs) const{ + return (*this == uint256_t(rhs)); +} + +bool uint256_t::operator==(const uint256_t & rhs) const{ + return ((UPPER == rhs.UPPER) && (LOWER == rhs.LOWER)); +} + +bool uint256_t::operator!=(const uint128_t & rhs) const{ + return (*this != uint256_t(rhs)); +} + +bool uint256_t::operator!=(const uint256_t & rhs) const{ + return ((UPPER != rhs.UPPER) | (LOWER != rhs.LOWER)); +} + +bool uint256_t::operator>(const uint128_t & rhs) const{ + return (*this > uint256_t(rhs)); +} + +bool uint256_t::operator>(const uint256_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER > rhs.LOWER); + } + if (UPPER > rhs.UPPER){ + return true; + } + return false; +} + +bool uint256_t::operator<(const uint128_t & rhs) const{ + return (*this < uint256_t(rhs)); +} + +bool uint256_t::operator<(const uint256_t & rhs) const{ + if (UPPER == rhs.UPPER){ + return (LOWER < rhs.LOWER); + } + if (UPPER < rhs.UPPER){ + return true; + } + return false; +} + +bool uint256_t::operator>=(const uint128_t & rhs) const{ + return (*this >= uint256_t(rhs)); +} + +bool uint256_t::operator>=(const uint256_t & rhs) const{ + return ((*this > rhs) | (*this == rhs)); +} + +bool uint256_t::operator<=(const uint128_t & rhs) const{ + return (*this <= uint256_t(rhs)); +} + +bool uint256_t::operator<=(const uint256_t & rhs) const{ + return ((*this < rhs) | (*this == rhs)); +} + +uint256_t uint256_t::operator+(const uint128_t & rhs) const{ + return *this + uint256_t(rhs); +} + +uint256_t uint256_t::operator+(const uint256_t & rhs) const{ + return uint256_t(UPPER + rhs.UPPER + (((LOWER + rhs.LOWER) < LOWER)?uint128_1:uint128_0), LOWER + rhs.LOWER); +} + +uint256_t & uint256_t::operator+=(const uint128_t & rhs){ + return *this += uint256_t(rhs); +} + +uint256_t & uint256_t::operator+=(const uint256_t & rhs){ + UPPER = rhs.UPPER + UPPER + ((LOWER + rhs.LOWER) < LOWER); + LOWER = LOWER + rhs.LOWER; + return *this; +} + +uint256_t uint256_t::operator-(const uint128_t & rhs) const{ + return *this - uint256_t(rhs); +} + +uint256_t uint256_t::operator-(const uint256_t & rhs) const{ + return uint256_t(UPPER - rhs.UPPER - ((LOWER - rhs.LOWER) > LOWER), LOWER - rhs.LOWER); +} + +uint256_t & uint256_t::operator-=(const uint128_t & rhs){ + return *this -= uint256_t(rhs); +} + +uint256_t & uint256_t::operator-=(const uint256_t & rhs){ + *this = *this - rhs; + return *this; +} + +uint256_t uint256_t::operator*(const uint128_t & rhs) const{ + return *this * uint256_t(rhs); +} + +uint256_t uint256_t::operator*(const uint256_t & rhs) const{ + // split values into 4 64-bit parts + uint128_t top[4] = {UPPER.upper(), UPPER.lower(), LOWER.upper(), LOWER.lower()}; + uint128_t bottom[4] = {rhs.upper().upper(), rhs.upper().lower(), rhs.lower().upper(), rhs.lower().lower()}; + uint128_t products[4][4]; + + // multiply each component of the values + for(int y = 3; y > -1; y--){ + for(int x = 3; x > -1; x--){ + products[3 - y][x] = top[x] * bottom[y]; + } + } + + // first row + uint128_t fourth64 = uint128_t(products[0][3].lower()); + uint128_t third64 = uint128_t(products[0][2].lower()) + uint128_t(products[0][3].upper()); + uint128_t second64 = uint128_t(products[0][1].lower()) + uint128_t(products[0][2].upper()); + uint128_t first64 = uint128_t(products[0][0].lower()) + uint128_t(products[0][1].upper()); + + // second row + third64 += uint128_t(products[1][3].lower()); + second64 += uint128_t(products[1][2].lower()) + uint128_t(products[1][3].upper()); + first64 += uint128_t(products[1][1].lower()) + uint128_t(products[1][2].upper()); + + // third row + second64 += uint128_t(products[2][3].lower()); + first64 += uint128_t(products[2][2].lower()) + uint128_t(products[2][3].upper()); + + // fourth row + first64 += uint128_t(products[3][3].lower()); + + // combines the values, taking care of carry over + return uint256_t(first64 << uint128_64, uint128_0) + + uint256_t(third64.upper(), third64 << uint128_64) + + uint256_t(second64, uint128_0) + + uint256_t(fourth64); +} + +uint256_t & uint256_t::operator*=(const uint128_t & rhs){ + return *this *= uint256_t(rhs); +} + +uint256_t & uint256_t::operator*=(const uint256_t & rhs){ + *this = *this * rhs; + return *this; +} + +std::pair uint256_t::divmod(const uint256_t & lhs, const uint256_t & rhs) const{ + // Save some calculations ///////////////////// + if (rhs == uint256_0){ + throw std::domain_error("Error: division or modulus by 0"); + } + else if (rhs == uint256_1){ + return std::pair (lhs, uint256_0); + } + else if (lhs == rhs){ + return std::pair (uint256_1, uint256_0); + } + else if ((lhs == uint256_0) || (lhs < rhs)){ + return std::pair (uint256_0, lhs); + } + + std::pair qr(uint256_0, lhs); + uint256_t copyd = rhs << (lhs.bits() - rhs.bits()); + uint256_t adder = uint256_1 << (lhs.bits() - rhs.bits()); + if (copyd > qr.second){ + copyd >>= uint256_1; + adder >>= uint256_1; + } + while (qr.second >= rhs){ + if (qr.second >= copyd){ + qr.second -= copyd; + qr.first |= adder; + } + copyd >>= uint256_1; + adder >>= uint256_1; + } + return qr; +} + +uint256_t uint256_t::operator/(const uint128_t & rhs) const{ + return *this / uint256_t(rhs); +} + +uint256_t uint256_t::operator/(const uint256_t & rhs) const{ + return divmod(*this, rhs).first; +} + +uint256_t & uint256_t::operator/=(const uint128_t & rhs){ + return *this /= uint256_t(rhs); +} + +uint256_t & uint256_t::operator/=(const uint256_t & rhs){ + *this = *this / rhs; + return *this; +} + +uint256_t uint256_t::operator%(const uint128_t & rhs) const{ + return *this % uint256_t(rhs); +} + +uint256_t uint256_t::operator%(const uint256_t & rhs) const{ + return *this - (rhs * (*this / rhs)); +} + +uint256_t & uint256_t::operator%=(const uint128_t & rhs){ + return *this %= uint256_t(rhs); +} + +uint256_t & uint256_t::operator%=(const uint256_t & rhs){ + *this = *this % rhs; + return *this; +} + +uint256_t & uint256_t::operator++(){ + *this += uint256_1; + return *this; +} + +uint256_t uint256_t::operator++(int){ + uint256_t temp(*this); + ++*this; + return temp; +} + +uint256_t & uint256_t::operator--(){ + *this -= uint256_1; + return *this; +} + +uint256_t uint256_t::operator--(int){ + uint256_t temp(*this); + --*this; + return temp; +} + +uint256_t uint256_t::operator+() const{ + return *this; +} + +uint256_t uint256_t::operator-() const{ + return ~*this + uint256_1; +} + +const uint128_t & uint256_t::upper() const { + return UPPER; +} + +const uint128_t & uint256_t::lower() const { + return LOWER; +} + +std::vector uint256_t::export_bits() const { + std::vector ret; + ret.reserve(32); + UPPER.export_bits(ret); + LOWER.export_bits(ret); + return ret; +} + +std::vector uint256_t::export_bits_truncate() const { + std::vector ret = export_bits(); + + //prune the zeroes + int i = 0; + while (ret[i] == 0 && i < 64) i++; + ret.erase(ret.begin(), ret.begin() + i); + + return ret; +} + +uint16_t uint256_t::bits() const{ + uint16_t out = 0; + if (UPPER){ + out = 128; + uint128_t up = UPPER; + while (up){ + up >>= uint128_1; + out++; + } + } + else{ + uint128_t low = LOWER; + while (low){ + low >>= uint128_1; + out++; + } + } + return out; +} + +std::string uint256_t::str(uint8_t base, const unsigned int & len) const{ + if ((base < 2) || (base > 36)){ + throw std::invalid_argument("Base must be in the range 2-36"); + } + std::string out = ""; + if (!(*this)){ + out = "0"; + } + else{ + std::pair qr(*this, uint256_0); + do{ + qr = divmod(qr.first, base); + out = "0123456789abcdefghijklmnopqrstuvwxyz"[(uint8_t) qr.second] + out; + } while (qr.first); + } + if (out.size() < len){ + out = std::string(len - out.size(), '0') + out; + } + return out; +} + +uint256_t operator&(const uint128_t & lhs, const uint256_t & rhs){ + return rhs & lhs; +} + +uint128_t & operator&=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs & lhs).lower(); + return lhs; +} + +uint256_t operator|(const uint128_t & lhs, const uint256_t & rhs){ + return rhs | lhs; +} + +uint128_t & operator|=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs | lhs).lower(); + return lhs; +} + +uint256_t operator^(const uint128_t & lhs, const uint256_t & rhs){ + return rhs ^ lhs; +} + +uint128_t & operator^=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs ^ lhs).lower(); + return lhs; +} + +uint256_t operator<<(const bool & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint256_t operator<<(const int64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) << rhs; +} + +uint128_t & operator<<=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) << rhs).lower(); + return lhs; +} + +uint256_t operator>>(const bool & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int8_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int16_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int32_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint256_t operator>>(const int64_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) >> rhs; +} + +uint128_t & operator>>=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) >> rhs).lower(); + return lhs; +} + +// Comparison Operators +bool operator==(const uint128_t & lhs, const uint256_t & rhs){ + return rhs == lhs; +} + +bool operator!=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs != lhs; +} + +bool operator>(const uint128_t & lhs, const uint256_t & rhs){ + return rhs < lhs; +} + +bool operator<(const uint128_t & lhs, const uint256_t & rhs){ + return rhs > lhs; +} + +bool operator>=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs <= lhs; +} + +bool operator<=(const uint128_t & lhs, const uint256_t & rhs){ + return rhs >= lhs; +} + +// Arithmetic Operators +uint256_t operator+(const uint128_t & lhs, const uint256_t & rhs){ + return rhs + lhs; +} + +uint128_t & operator+=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs + lhs).lower(); + return lhs; +} + +uint256_t operator-(const uint128_t & lhs, const uint256_t & rhs){ + return -(rhs - lhs); +} + +uint128_t & operator-=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (-(rhs - lhs)).lower(); + return lhs; +} + +uint256_t operator*(const uint128_t & lhs, const uint256_t & rhs){ + return rhs * lhs; +} + +uint128_t & operator*=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (rhs * lhs).lower(); + return lhs; +} + +uint256_t operator/(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) / rhs; +} + +uint128_t & operator/=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) / rhs).lower(); + return lhs; +} + +uint256_t operator%(const uint128_t & lhs, const uint256_t & rhs){ + return uint256_t(lhs) % rhs; +} + +uint128_t & operator%=(uint128_t & lhs, const uint256_t & rhs){ + lhs = (uint256_t(lhs) % rhs).lower(); + return lhs; +} + +std::ostream & operator<<(std::ostream & stream, const uint256_t & rhs){ + if (stream.flags() & stream.oct){ + stream << rhs.str(8); + } + else if (stream.flags() & stream.dec){ + stream << rhs.str(10); + } + else if (stream.flags() & stream.hex){ + stream << rhs.str(16); + } + return stream; +} diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.h b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.h new file mode 100644 index 0000000..8013b41 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.h @@ -0,0 +1,9 @@ +// PUBLIC IMPORT HEADER +#ifndef _UINT256_H_ +#define _UINT256_H_ +#include "uint256_t_config.include" +#define UINT256_T_EXTERN _UINT256_T_IMPORT +#include "uint128_t.include" +#include "uint256_t.include" +#endif + diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.include b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.include new file mode 100644 index 0000000..84898d0 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.include @@ -0,0 +1,583 @@ +/* +uint256_t.h +An unsigned 256 bit integer library for C++ + +Copyright (c) 2013 - 2017 Jason Lee @ calccrypto at gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +With much help from Auston Sterling + +Thanks to François Dessenne for convincing me +to do a general rewrite of this class. +*/ + +#ifndef __UINT256_T__ +#define __UINT256_T__ + +#include +#include +#include +#include +#include + +class UINT256_T_EXTERN uint256_t; + +// Give uint256_t type traits +namespace std { // This is probably not a good idea + template <> struct is_arithmetic : std::true_type {}; + template <> struct is_integral : std::true_type {}; + template <> struct is_unsigned : std::true_type {}; +}; + +class uint256_t{ + private: + uint128_t UPPER, LOWER; + + public: + // Constructors + uint256_t(); + uint256_t(const uint256_t & rhs); + uint256_t(uint256_t && rhs); + uint256_t(const std::string & s); + uint256_t(const char *val); + + template ::value, T>::type > + uint256_t(const T & rhs) + : UPPER(uint128_0), LOWER(rhs) + {} + + template ::value && std::is_integral::value, void>::type> + uint256_t(const S & upper_rhs, const T & lower_rhs) + : UPPER(upper_rhs), LOWER(lower_rhs) + {} + template ::value && + std::is_integral::value && + std::is_integral::value && + std::is_integral::value, void>::type> + uint256_t(const R & upper_lhs, const S & lower_lhs, const T & upper_rhs, const U & lower_rhs) + : UPPER(upper_lhs, lower_lhs), LOWER(upper_rhs, lower_rhs) + {} + + // RHS input args only + std::vector export_bits() const; + std::vector export_bits_truncate() const; + + // Assignment Operator + uint256_t & operator=(const uint256_t & rhs); + uint256_t & operator=(uint256_t && rhs); + + template ::value, T>::type> + uint256_t & operator=(const T & rhs){ + UPPER = uint128_0; + LOWER = rhs; + return *this; + } + + // Typecast Operators + operator bool () const; + operator uint8_t () const; + operator uint16_t () const; + operator uint32_t () const; + operator uint64_t () const; + operator uint128_t () const; + + // Bitwise Operators + uint256_t operator&(const uint128_t & rhs) const; + uint256_t operator&(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator&(const T & rhs) const{ + return uint256_t(uint128_0, LOWER & (uint128_t) rhs); + } + + uint256_t & operator&=(const uint128_t & rhs); + uint256_t & operator&=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator&=(const T & rhs){ + UPPER = uint128_0; + LOWER &= rhs; + return *this; + } + + uint256_t operator|(const uint128_t & rhs) const; + uint256_t operator|(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator|(const T & rhs) const{ + return uint256_t(UPPER, LOWER | uint128_t(rhs)); + } + + uint256_t & operator|=(const uint128_t & rhs); + uint256_t & operator|=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator|=(const T & rhs){ + LOWER |= (uint128_t) rhs; + return *this; + } + + uint256_t operator^(const uint128_t & rhs) const; + uint256_t operator^(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator^(const T & rhs) const{ + return uint256_t(UPPER, LOWER ^ (uint128_t) rhs); + } + + uint256_t & operator^=(const uint128_t & rhs); + uint256_t & operator^=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator^=(const T & rhs){ + LOWER ^= (uint128_t) rhs; + return *this; + } + + uint256_t operator~() const; + + // Bit Shift Operators + uint256_t operator<<(const uint128_t & shift) const; + uint256_t operator<<(const uint256_t & shift) const; + + template ::value, T>::type > + uint256_t operator<<(const T & rhs) const{ + return *this << uint256_t(rhs); + } + + uint256_t & operator<<=(const uint128_t & shift); + uint256_t & operator<<=(const uint256_t & shift); + + template ::value, T>::type > + uint256_t & operator<<=(const T & rhs){ + *this = *this << uint256_t(rhs); + return *this; + } + + uint256_t operator>>(const uint128_t & shift) const; + uint256_t operator>>(const uint256_t & shift) const; + + template ::value, T>::type > + uint256_t operator>>(const T & rhs) const{ + return *this >> uint256_t(rhs); + } + + uint256_t & operator>>=(const uint128_t & shift); + uint256_t & operator>>=(const uint256_t & shift); + + template ::value, T>::type > + uint256_t & operator>>=(const T & rhs){ + *this = *this >> uint256_t(rhs); + return *this; + } + + // Logical Operators + bool operator!() const; + + bool operator&&(const uint128_t & rhs) const; + bool operator&&(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator&&(const T & rhs) const{ + return ((bool) *this && rhs); + } + + bool operator||(const uint128_t & rhs) const; + bool operator||(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator||(const T & rhs) const{ + return ((bool) *this || rhs); + } + + // Comparison Operators + bool operator==(const uint128_t & rhs) const; + bool operator==(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator==(const T & rhs) const{ + return (!UPPER && (LOWER == uint128_t(rhs))); + } + + bool operator!=(const uint128_t & rhs) const; + bool operator!=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator!=(const T & rhs) const{ + return ((bool) UPPER | (LOWER != uint128_t(rhs))); + } + + bool operator>(const uint128_t & rhs) const; + bool operator>(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator>(const T & rhs) const{ + return ((bool) UPPER | (LOWER > uint128_t(rhs))); + } + + bool operator<(const uint128_t & rhs) const; + bool operator<(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator<(const T & rhs) const{ + return (!UPPER)?(LOWER < uint128_t(rhs)):false; + } + + bool operator>=(const uint128_t & rhs) const; + bool operator>=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator>=(const T & rhs) const{ + return ((*this > rhs) | (*this == rhs)); + } + + bool operator<=(const uint128_t & rhs) const; + bool operator<=(const uint256_t & rhs) const; + + template ::value, T>::type > + bool operator<=(const T & rhs) const{ + return ((*this < rhs) | (*this == rhs)); + } + + // Arithmetic Operators + uint256_t operator+(const uint128_t & rhs) const; + uint256_t operator+(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator+(const T & rhs) const{ + return uint256_t(UPPER + ((LOWER + (uint128_t) rhs) < LOWER), LOWER + (uint128_t) rhs); + } + + uint256_t & operator+=(const uint128_t & rhs); + uint256_t & operator+=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator+=(const T & rhs){ + UPPER = UPPER + ((LOWER + rhs) < LOWER); + LOWER = LOWER + rhs; + return *this; + } + + uint256_t operator-(const uint128_t & rhs) const; + uint256_t operator-(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator-(const T & rhs) const{ + return uint256_t(UPPER - ((LOWER - rhs) > LOWER), LOWER - rhs); + } + + uint256_t & operator-=(const uint128_t & rhs); + uint256_t & operator-=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator-=(const T & rhs){ + *this = *this - rhs; + return *this; + } + + uint256_t operator*(const uint128_t & rhs) const; + uint256_t operator*(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator*(const T & rhs) const{ + return *this * uint256_t(rhs); + } + + uint256_t & operator*=(const uint128_t & rhs); + uint256_t & operator*=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator*=(const T & rhs){ + *this = *this * uint256_t(rhs); + return *this; + } + + private: + std::pair divmod(const uint256_t & lhs, const uint256_t & rhs) const; + void init(const char * s); + + public: + uint256_t operator/(const uint128_t & rhs) const; + uint256_t operator/(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator/(const T & rhs) const{ + return *this / uint256_t(rhs); + } + + uint256_t & operator/=(const uint128_t & rhs); + uint256_t & operator/=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator/=(const T & rhs){ + *this = *this / uint256_t(rhs); + return *this; + } + + uint256_t operator%(const uint128_t & rhs) const; + uint256_t operator%(const uint256_t & rhs) const; + + template ::value, T>::type > + uint256_t operator%(const T & rhs) const{ + return *this % uint256_t(rhs); + } + + uint256_t & operator%=(const uint128_t & rhs); + uint256_t & operator%=(const uint256_t & rhs); + + template ::value, T>::type > + uint256_t & operator%=(const T & rhs){ + *this = *this % uint256_t(rhs); + return *this; + } + + // Increment Operators + uint256_t & operator++(); + uint256_t operator++(int); + + // Decrement Operators + uint256_t & operator--(); + uint256_t operator--(int); + + // Nothing done since promotion doesn't work here + uint256_t operator+() const; + + // two's complement + uint256_t operator-() const; + + // Get private values + const uint128_t & upper() const; + const uint128_t & lower() const; + + // Get bitsize of value + uint16_t bits() const; + + // Get string representation of value + std::string str(uint8_t base = 10, const unsigned int & len = 0) const; +}; + +// useful values +UINT256_T_EXTERN extern const uint128_t uint128_64; +UINT256_T_EXTERN extern const uint128_t uint128_128; +UINT256_T_EXTERN extern const uint128_t uint128_256; +UINT256_T_EXTERN extern const uint256_t uint256_0; +UINT256_T_EXTERN extern const uint256_t uint256_1; +UINT256_T_EXTERN extern const uint256_t uint256_max; + +// Bitwise Operators +UINT256_T_EXTERN uint256_t operator&(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > + uint256_t operator&(const T & lhs, const uint256_t & rhs){ + return rhs & lhs; +} + +UINT256_T_EXTERN uint128_t & operator&=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator&=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs & lhs); +} + +UINT256_T_EXTERN uint256_t operator|(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator|(const T & lhs, const uint256_t & rhs){ + return rhs | lhs; +} + +UINT256_T_EXTERN uint128_t & operator|=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator|=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs | lhs); +} + +UINT256_T_EXTERN uint256_t operator^(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator^(const T & lhs, const uint256_t & rhs){ + return rhs ^ lhs; +} + +uint128_t & operator^=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator^=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs ^ lhs); +} + +// Bitshift operators +UINT256_T_EXTERN uint256_t operator<<(const bool & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint64_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const uint128_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator<<(const int64_t & lhs, const uint256_t & rhs); + +UINT256_T_EXTERN uint128_t & operator<<=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator<<=(T & lhs, const uint256_t & rhs){ + lhs = static_cast (uint256_t(lhs) << rhs); + return lhs; +} + +UINT256_T_EXTERN uint256_t operator>>(const bool & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint64_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const uint128_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int8_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int16_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int32_t & lhs, const uint256_t & rhs); +UINT256_T_EXTERN uint256_t operator>>(const int64_t & lhs, const uint256_t & rhs); + +UINT256_T_EXTERN uint128_t & operator>>=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator>>=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) >> rhs); +} + +// Comparison Operators +UINT256_T_EXTERN bool operator==(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator==(const T & lhs, const uint256_t & rhs){ + return (!rhs.upper() && ((uint64_t) lhs == rhs.lower())); +} + +UINT256_T_EXTERN bool operator!=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator!=(const T & lhs, const uint256_t & rhs){ + return (rhs.upper() | ((uint64_t) lhs != rhs.lower())); +} + +UINT256_T_EXTERN bool operator>(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator>(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?false:((uint128_t) lhs > rhs.lower()); +} + +UINT256_T_EXTERN bool operator<(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator<(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?true:((uint128_t) lhs < rhs.lower()); +} + +UINT256_T_EXTERN bool operator>=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator>=(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?false:((uint128_t) lhs >= rhs.lower()); +} + +UINT256_T_EXTERN bool operator<=(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +bool operator<=(const T & lhs, const uint256_t & rhs){ + return rhs.upper()?true:((uint128_t) lhs <= rhs.lower()); +} + +// Arithmetic Operators +UINT256_T_EXTERN uint256_t operator+(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator+(const T & lhs, const uint256_t & rhs){ + return rhs + lhs; +} + +UINT256_T_EXTERN uint128_t & operator+=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator+=(T & lhs, const uint256_t & rhs){ + lhs = static_cast (rhs + lhs); + return lhs; +} + +UINT256_T_EXTERN uint256_t operator-(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator-(const T & lhs, const uint256_t & rhs){ + return -(rhs - lhs); +} + +UINT256_T_EXTERN uint128_t & operator-=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator-=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (-(rhs - lhs)); +} + +UINT256_T_EXTERN uint256_t operator*(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator*(const T & lhs, const uint256_t & rhs){ + return rhs * lhs; +} + +UINT256_T_EXTERN uint128_t & operator*=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator*=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (rhs * lhs); +} + +UINT256_T_EXTERN uint256_t operator/(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator/(const T & lhs, const uint256_t & rhs){ + return uint256_t(lhs) / rhs; +} + +UINT256_T_EXTERN uint128_t & operator/=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator/=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) / rhs); +} + +UINT256_T_EXTERN uint256_t operator%(const uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +uint256_t operator%(const T & lhs, const uint256_t & rhs){ + return uint256_t(lhs) % rhs; +} + +UINT256_T_EXTERN uint128_t & operator%=(uint128_t & lhs, const uint256_t & rhs); + +template ::value, T>::type > +T & operator%=(T & lhs, const uint256_t & rhs){ + return lhs = static_cast (uint256_t(lhs) % rhs); +} + +// IO Operator +UINT256_T_EXTERN std::ostream & operator<<(std::ostream & stream, const uint256_t & rhs); +#endif diff --git a/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t_config.include b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t_config.include new file mode 100644 index 0000000..e83db51 --- /dev/null +++ b/Office Door/.pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t_config.include @@ -0,0 +1,19 @@ +#ifndef _UINT256_T_CONFIG_ + #define _UINT256_T_CONFIG_ + #if defined(_MSC_VER) + #if defined(_DLL) + #define _UINT256_T_EXPORT __declspec(dllexport) + #define _UINT256_T_IMPORT __declspec(dllimport) + #else + #define _UINT256_T_EXPORT + #define _UINT256_T_IMPORT + #endif + #else + // All modules on Unix are compiled with -fvisibility=hidden + // All API symbols get visibility default + // whether or not we're static linking or dynamic linking (with -fPIC) + #define _UINT256_T_EXPORT __attribute__((visibility("default"))) + #define _UINT256_T_IMPORT __attribute__((visibility("default"))) + #endif +#endif + diff --git a/Office Door/.vscode/extensions.json b/Office Door/.vscode/extensions.json index 272828b..0f0d740 100644 --- a/Office Door/.vscode/extensions.json +++ b/Office Door/.vscode/extensions.json @@ -1,7 +1,7 @@ -{ - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "platformio.platformio-ide" - ] -} \ No newline at end of file +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/Office Door/platformio.ini b/Office Door/platformio.ini index b6b9110..76c0d6c 100644 --- a/Office Door/platformio.ini +++ b/Office Door/platformio.ini @@ -12,11 +12,7 @@ platform = espressif32 board = esp32dev framework = arduino - -; Serial Monitor options monitor_speed = 115200 - -lib_deps = - # Using a library name - Web3E - ESP8266_SSD1306 +lib_deps = + Web3E + ESP8266_SSD1306 diff --git a/Office Door/src/main.cpp b/Office Door/src/main.cpp index 0db88a9..224d6b7 100644 --- a/Office Door/src/main.cpp +++ b/Office Door/src/main.cpp @@ -23,11 +23,10 @@ const char *INFURA_PATH = "/v3/c7df4c29472d4d54a39f7aa78f146853"; #define GATE_PIN 12 // ID of the pin the door relay is connected to #define BLUE_LED 2 // Little blue LED on the ESP8266/ESP32 -//use these if you want to expose your DApp server to outside world via portforwarding -// IPAddress ipStat(192, 168, 1, 85); -// IPAddress gateway(192, 168, 1, 1); -// IPAddress subnet(255, 255, 255, 0); -// IPAddress dns(192, 168, 1, 1); +IPAddress ipStat(192, 168, 1, 250); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 255, 0); +IPAddress dns(192, 168, 1, 1); Web3 web3(INFURA_HOST, INFURA_PATH); WiFiServer server(80);