Compare commits

..

3 Commits

Author SHA1 Message Date
Kevin F
cb977a2719 Removed more defunct code 2022-08-03 12:18:21 -05:00
Kevin F
e1b4b12024 Remove defunct requirements 2022-08-03 11:43:59 -05:00
Kevin F
f435a6e6fa Removed webUI and unused god objects 2022-08-03 00:23:22 -05:00
214 changed files with 4529 additions and 3049 deletions

12
AUTHORS.MD Normal file
View File

@ -0,0 +1,12 @@
# Incomplete List of Contributors
Onionr is created by a team of hard working volunteers.
In no order of importance, these people make Onionr happen:
* [Beardog (Kevin Froman)](https://www.chaoswebs.net/) - Project founder, owner and core developer
* [InvisaMage](https://invisamage.com/) - Web UI Bulma design
* [Arinerron](https://arinerron.com/) - Logger and config modules, testing and other contributions
* [Anhar Ismail](https://github.com/anharismail) - Created Onionr's logo
+ Other contributors and testers

View File

@ -1,4 +1,4 @@
FROM python:3.10
FROM python:3.7
EXPOSE 8080
USER root
@ -15,7 +15,7 @@ RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
ADD ./requirements-x86-all-plugins.txt /app/requirements.txt
ADD ./requirements.txt /app/requirements.txt
RUN pip3 install --require-hashes -r requirements.txt
#Add Onionr source
@ -28,4 +28,4 @@ RUN chmod g=u -R /app
USER 1000
ENV HOME=/app
CMD ["bash", "./onionr.sh", "start"]
CMD ["bash", "./run-onionr-node.sh"]

View File

@ -11,23 +11,23 @@
WIP anonymous social platform, mail, file sharing and marketplace
</p>
<img src="https://img.shields.io/badge/License-aGPLv3-yellow"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.10+-blue'>
<img src="https://img.shields.io/badge/License-aGPLv3-yellow"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.7+-blue'>
<a href='https://twitter.com/onionrnet'><img src='https://img.shields.io/twitter/follow/onionrnet?style=social'></a> - [Discord](https://discord.gg/DVF2bEAzrt) - Matrix: #onionr:amorgan.xyz
| | | |
| ----------- | ----------- | ----------- |
| [Install](#install-and-run-on-linux) | [Features](#main-features) | [Screenshots](#screenshots)|
| [Docs](#documentation) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
| [Docs](#documentation)/[web copy](https://beardog108.github.io/onionr/) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
---
**The main repository for this software is at https://gitlab.com/beardog/onionr/**
**The main repository for this software is at https://git.VoidNet.tech/kev/onionr/**
***Note that this README reflects the state of the rewrite, and not the original alpha network***
Mirrors [Gitea](https://git.voidnet.tech/kev/onionr)
Mirrors [Gitlab](https://gitlab.com/beardog/onionr)
Onionr ("Onion Relay") is a decentralized/distributed peer-to-peer communication network, designed to be anonymous and resistant to (meta)data analysis, spam, and corruption.
@ -84,13 +84,14 @@ Master may be unstable, you should use the latest release tag. (checkout via git
`$ sudo apt install python3-pip python3-dev tor`
* Have python3.10, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
* Have python3.7+, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
* You may need build-essentials or the equivalent of your platform
* Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr --tags`
* cd into install direction: `$ cd onionr/`
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements-x86-all-plugins.txt`
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements.txt` (on ARM64 devices like Raspberry Pi 4's use requirements-ARM.txt instead.)
* (Optional): Install desktop notification dependencies: `$ pip3 install --require-hashes -r requirements-notifications.txt`
Require-hashes is suggested for supply-chain security but is optional. The hashes are not correct for ARM machines. If you are just running a node or want a bare-bones install you can use requirements-base-x86.txt and selectively install the requirements.txt files in static-data/official-plugins/ subdirectories
(--require-hashes is intended to prevent exploitation via compromise of PyPi/CA certificates)
## Run Onionr

View File

@ -6,32 +6,32 @@
* [ X ] Implement new block format with verifiable delay function
* [ X ] Implement overhauled gossip system with dandelion++
* [ ] Implement overhauled gossip system with dandelion++
The new system is separated from the underlying networks used and makes it much easier to implement new transport methods. Dandelion++ is also better than the old block mixing we did.
* [ ] Revamped key/encrypted messaging (encrypted blocks)
* [ ] Restore webUI as a plugin
* [ ] Restore static site/file sharing plugin
* [ ] Restore/reimplement mail plugin
* [ ] Restore/reimplement friends plugin
* [ ] Refresh test suite
## Misc
* [ ] Spruce up documentation
* [ ] Restore LAN transport
* [ ] Restore webUI as a plugin
* [ ] Restore static site/file sharing plugin
* [ ] Restore/reimplement mail plugin
* [ ] Restore/reimplement friends plugin
* [ ] Refresh test suite
* [ ] Revamped key/encrypted messaging (encrypted blocks)
## Web of trust release (~10.0)
## Web of trust release (10.0)
To facilitate the below market plugin/application, Onionr will need a web of trust system.
* [ ] Web of trust plugin or module
## Market Plugin Release (~10.1)
## Market Plugin Release (10.1)
The Onionr team believes the Monero community is currently lacking a good p2p market, and as such we hope to build a solution using Onionr as a transport. This may be a separate project and as opposed to a plugin.

124
docs/dev/http-api.md Executable file
View File

@ -0,0 +1,124 @@
# Onionr HTTP API
All HTTP interfaces in the Onionr reference client use the [Flask](http://flask.pocoo.org/) web framework with the [gevent](http://www.gevent.org/) WSGI server.
## Client & Public difference
The client API server is a locked down interface intended for authenticated local communication.
The public API server is available only remotely from Tor & I2P. It is the interface in which peers use to communicate with one another.
# Client API
Please note: endpoints that simply provide static web app files are not documented here.
* /serviceactive/pubkey
- Methods: GET
- Returns true or false based on if a given public key has an active direct connection service.
* /queueResponseAdd/key (DEPRECATED)
- Methods: POST
- Accepts form key 'data' to set queue response information from a plugin
- Returns success if no error occurs
* /queueResponse/key (DEPRECATED)
- Methods: GET
- Returns the queue response for a key. Returns failure with a 404 code if a code is not set.
* /ping
- Methods: GET
- Returns "pong!"
* /getblocksbytype/type
- Methods: GET
- Returns a list of stored blocks by a given type
* /getblockbody/hash
- Methods: GET
- Returns the main data section of a block
* /getblockdata/hash
- Methods: GET
- Returns the entire data contents of a block, including metadata.
* /getblockheader/hash
- Methods: GET
- Returns the header (metadata section) of a block.
* /gethidden/
- Methods: GET
- Returns line separated list of hidden blocks
* /hitcount
- Methods: GET
- Return the amount of requests the public api server has received this session
* /lastconnect
- Methods: GET
- Returns the epoch timestamp of when the last incoming connection to the public API server was logged
* /site/hash
- Methods: GET
- Returns HTML content out of a block
* /waitforshare/hash
- Methods: POST
- Prevents the public API server from listing or sharing a block until it has been uploaded to at least 1 peer.
* /shutdown
- Methods: GET
- Shutdown Onionr. You should probably use /shutdownclean instead.
* /shutdownclean
- Methods: GET
- Tells the communicator daemon to shutdown Onionr. Slower but cleaner.
* /getstats
- Methods: GET
- Returns some JSON serialized statistics
* /getuptime
- Methods: GET
- Returns uptime in seconds
* /getActivePubkey
- Methods: GET
- Returns the current active public key in base32 format
* /getHumanReadable/pubkey
- Methods: GET
- Echos the specified public key in mnemonic format
* /insertblock
- Methods: POST
- Accepts JSON data for creating a new block. 'message' contains the block data, 'to' specifies the peer's public key to encrypt the data to, 'sign' is a boolean for signing the message.
* /torready
- Methods: POST
- Returns boolean if Tor is started or not
# Public API
v0
* /
- Methods: GET
- Returns a basic HTML informational banner describing Onionr.
* /getblocklist
- Methods: GET
- URI Parameters:
- date: unix epoch timestamp for offset
- Returns a list of block hashes stored on the node since an offset (all blocks if no timestamp is specified)
* /getdata/block-hash
- Methods: GET
- Returns data for a block based on a provided hash
* /www/file-path
- Methods: GET
- Returns file data. Intended for manually sharing file data directly from an Onionr node.
* /ping
- Methods: GET
- Returns 'pong!'
* /pex
- Methods: GET
- Returns a list of peer addresses reached within recent time
* /announce
- Methods: POST
- Accepts form data for 'node' (valid node address) and 'random' which is a nonce when hashed (blake2b_256) in the format `hash(peerAddress+serverAddress+nonce)`, begins with at least 5 zeros.
- Returns 200 with 'Success' if no error occurs. If the post is invalid, 'failure' with code 406 is returned.
* /upload
- Methods: POST
- Accepts form data for 'block' as a 'file' upload.
- Returns 200 with 'success' if no error occurs. If the block cannot be accepted, 'failure' with 400 is returned.
# Direct Connection API
These are constant endpoints available on direct connection servers. Plugin endpoints for direct connections are not documented here.
* /ping
- Methods: GET
- Returns 200 with 'pong!'
* /close
- Methods: GET
- Kills the direct connection server, destroying the onion address.
- Returns 200 with 'goodbye'

View File

@ -2,8 +2,6 @@
ORIG_ONIONR_RUN_DIR=`pwd`
export ORIG_ONIONR_RUN_DIR
export PYTHONDONTWRITEBYTECODE=1
export PYTHONUNBUFFERED=1
export PYTHONOPTIMIZE="true"
cd "$(dirname "$0")"
cd src
./__init__.py "$@"

392
requirements-ARM.txt Normal file
View File

@ -0,0 +1,392 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-ARM.txt requirements.in
#
--extra-index-url https://www.piwheels.org/simple
certifi==2020.12.5 \
--hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \
--hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830
# via requests
cffi==1.14.4 \
--hash=sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e \
--hash=sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d \
--hash=sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a \
--hash=sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec \
--hash=sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362 \
--hash=sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668 \
--hash=sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c \
--hash=sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b \
--hash=sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06 \
--hash=sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698 \
--hash=sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2 \
--hash=sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c \
--hash=sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7 \
--hash=sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009 \
--hash=sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03 \
--hash=sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b \
--hash=sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909 \
--hash=sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53 \
--hash=sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35 \
--hash=sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26 \
--hash=sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b \
--hash=sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01 \
--hash=sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb \
--hash=sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293 \
--hash=sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd \
--hash=sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d \
--hash=sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3 \
--hash=sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d \
--hash=sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e \
--hash=sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca \
--hash=sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d \
--hash=sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775 \
--hash=sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375 \
--hash=sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b \
--hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \
--hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f
# via
# -r requirements.in
# pynacl
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
# via requests
click==7.1.2 \
--hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \
--hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc
# via flask
deadsimplekv==0.3.2 \
--hash=sha256:a725f4a9d1156ebb66b7535ac150006881e0365b715e34e3709214827b8b0c4c \
--hash=sha256:df00262d26c3dcfecb710425a7413059480d8cf026216042d7cbffb8514818b2
# via -r requirements.in
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements.in
flask==1.1.2 \
--hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \
--hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557
# via -r requirements.in
gevent==20.9.0 \
--hash=sha256:10110d4881aec04f218c316cb796b18c8b2cac67ae0eb5b0c5780056757268a2 \
--hash=sha256:1628a403fc9c3ea9b35924638a4d4fbe236f60ecdf4e22ed133fbbaf0bc7cb6b \
--hash=sha256:1cfa3674866294623e324fa5b76eba7b96744d1956a605cfe24d26c5cd890f91 \
--hash=sha256:2269574444113cb4ca1c1808ab9460a87fe25e1c34a6e36d975d4af46e4afff9 \
--hash=sha256:283a021a2e14adfad718346f18982b80569d9c3a59e97cfae1b7d4c5b017941a \
--hash=sha256:2aa70726ad1883fe7c17774e5ccc91ac6e30334efa29bafb9b8fe8ca6091b219 \
--hash=sha256:315a63a35068183dfb9bc0331c7bb3c265ee7db8a11797cbe98dadbdb45b5d35 \
--hash=sha256:324808a8558c733f7a9734525483795d52ca3bbd5662b24b361d81c075414b1f \
--hash=sha256:33a63f230755c6813fca39d9cea2a8894df32df2ee58fd69d8bf8fcc1d8e018e \
--hash=sha256:5f6d48051d336561ec08995431ee4d265ac723a64bba99cc58c3eb1a4d4f5c8d \
--hash=sha256:8d338cd6d040fe2607e5305dd7991b5960b3780ae01f804c2ac5760d31d3b2c6 \
--hash=sha256:906175e3fb25f377a0b581e79d3ed5a7d925c136ff92fd022bb3013e25f5f3a9 \
--hash=sha256:93980e51dd2e5f81899d644a0b6ef4a73008c679fcedd50e3b21cc3451ba2424 \
--hash=sha256:9bb477f514cf39dc20651b479bf1ad4f38b9a679be2bfa3e162ec0c3785dfa2a \
--hash=sha256:a8733a01974433d91308f8c44fa6cc13428b15bb39d46540657e260ff8852cb1 \
--hash=sha256:adbb267067f56696b2babced3d0856aa39dcf14b8ccd2dffa1fab587b00c6f80 \
--hash=sha256:afc177c37de41ce9c27d351ac84cbaf34407effcab5d6641645838f39d365be1 \
--hash=sha256:b07fcbca3e819296979d82fac3d8b44f0d5ced57b9a04dffcfd194da99c8eb2d \
--hash=sha256:b2948566003a1030e47507755fe1f446995e8671c0c67571091539e01faf94cc \
--hash=sha256:db208e74a32cff7f55f5aa1ba5d7d1c1a086a6325c8702ae78a5c741155552ff \
--hash=sha256:dd4c6b2f540b25c3d0f277a725bc1a900ce30a681b90a081216e31f814be453b \
--hash=sha256:e11de4b4d107ca2f35000eb08e9c4c4621c153103b400f48a9ea95b96d8c7e0b \
--hash=sha256:eba19bae532d0c48d489fa16815b242ce074b1f4b63e8a8e663232cbe311ead9 \
--hash=sha256:fb33dc1ab27557bccd64ad4bf81e68c8b0d780fe937b1e2c0814558798137229
# via -r requirements.in
greenlet==1.0.0 \
--hash=sha256:0a77691f0080c9da8dfc81e23f4e3cffa5accf0f5b56478951016d7cfead9196 \
--hash=sha256:0ddd77586553e3daf439aa88b6642c5f252f7ef79a39271c25b1d4bf1b7cbb85 \
--hash=sha256:111cfd92d78f2af0bc7317452bd93a477128af6327332ebf3c2be7df99566683 \
--hash=sha256:122c63ba795fdba4fc19c744df6277d9cfd913ed53d1a286f12189a0265316dd \
--hash=sha256:181300f826625b7fd1182205b830642926f52bd8cdb08b34574c9d5b2b1813f7 \
--hash=sha256:1a1ada42a1fd2607d232ae11a7b3195735edaa49ea787a6d9e6a53afaf6f3476 \
--hash=sha256:1bb80c71de788b36cefb0c3bb6bfab306ba75073dbde2829c858dc3ad70f867c \
--hash=sha256:1d1d4473ecb1c1d31ce8fd8d91e4da1b1f64d425c1dc965edc4ed2a63cfa67b2 \
--hash=sha256:292e801fcb3a0b3a12d8c603c7cf340659ea27fd73c98683e75800d9fd8f704c \
--hash=sha256:2c65320774a8cd5fdb6e117c13afa91c4707548282464a18cf80243cf976b3e6 \
--hash=sha256:4365eccd68e72564c776418c53ce3c5af402bc526fe0653722bc89efd85bf12d \
--hash=sha256:5352c15c1d91d22902582e891f27728d8dac3bd5e0ee565b6a9f575355e6d92f \
--hash=sha256:58ca0f078d1c135ecf1879d50711f925ee238fe773dfe44e206d7d126f5bc664 \
--hash=sha256:5d4030b04061fdf4cbc446008e238e44936d77a04b2b32f804688ad64197953c \
--hash=sha256:5d69bbd9547d3bc49f8a545db7a0bd69f407badd2ff0f6e1a163680b5841d2b0 \
--hash=sha256:5f297cb343114b33a13755032ecf7109b07b9a0020e841d1c3cedff6602cc139 \
--hash=sha256:62afad6e5fd70f34d773ffcbb7c22657e1d46d7fd7c95a43361de979f0a45aef \
--hash=sha256:647ba1df86d025f5a34043451d7c4a9f05f240bee06277a524daad11f997d1e7 \
--hash=sha256:719e169c79255816cdcf6dccd9ed2d089a72a9f6c42273aae12d55e8d35bdcf8 \
--hash=sha256:7cd5a237f241f2764324396e06298b5dee0df580cf06ef4ada0ff9bff851286c \
--hash=sha256:875d4c60a6299f55df1c3bb870ebe6dcb7db28c165ab9ea6cdc5d5af36bb33ce \
--hash=sha256:90b6a25841488cf2cb1c8623a53e6879573010a669455046df5f029d93db51b7 \
--hash=sha256:94620ed996a7632723a424bccb84b07e7b861ab7bb06a5aeb041c111dd723d36 \
--hash=sha256:b5f1b333015d53d4b381745f5de842f19fe59728b65f0fbb662dafbe2018c3a5 \
--hash=sha256:c5b22b31c947ad8b6964d4ed66776bcae986f73669ba50620162ba7c832a6b6a \
--hash=sha256:c93d1a71c3fe222308939b2e516c07f35a849c5047f0197442a4d6fbcb4128ee \
--hash=sha256:cdb90267650c1edb54459cdb51dab865f6c6594c3a47ebd441bc493360c7af70 \
--hash=sha256:cfd06e0f0cc8db2a854137bd79154b61ecd940dce96fad0cba23fe31de0b793c \
--hash=sha256:d3789c1c394944084b5e57c192889985a9f23bd985f6d15728c745d380318128 \
--hash=sha256:da7d09ad0f24270b20f77d56934e196e982af0d0a2446120cb772be4e060e1a2 \
--hash=sha256:df3e83323268594fa9755480a442cabfe8d82b21aba815a71acf1bb6c1776218 \
--hash=sha256:df8053867c831b2643b2c489fe1d62049a98566b1646b194cc815f13e27b90df \
--hash=sha256:e1128e022d8dce375362e063754e129750323b67454cac5600008aad9f54139e \
--hash=sha256:e6e9fdaf6c90d02b95e6b0709aeb1aba5affbbb9ccaea5502f8638e4323206be \
--hash=sha256:eac8803c9ad1817ce3d8d15d1bb82c2da3feda6bee1153eec5c58fa6e5d3f770 \
--hash=sha256:eb333b90036358a0e2c57373f72e7648d7207b76ef0bd00a4f7daad1f79f5203 \
--hash=sha256:ed1d1351f05e795a527abc04a0d82e9aecd3bdf9f46662c36ff47b0b00ecaf06 \
--hash=sha256:f3dc68272990849132d6698f7dc6df2ab62a88b0d36e54702a8fd16c0490e44f \
--hash=sha256:f59eded163d9752fd49978e0bab7a1ff21b1b8d25c05f0995d140cc08ac83379 \
--hash=sha256:f5e2d36c86c7b03c94b8459c3bd2c9fe2c7dab4b258b8885617d44a22e453fb7 \
--hash=sha256:f6f65bf54215e4ebf6b01e4bb94c49180a589573df643735107056f7a910275b \
--hash=sha256:f8450d5ef759dbe59f84f2c9f77491bb3d3c44bc1a573746daf086e70b14c243 \
--hash=sha256:f97d83049715fd9dec7911860ecf0e17b48d8725de01e45de07d8ac0bd5bc378
# via gevent
idna==2.10 \
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
# via requests
itsdangerous==1.1.0 \
--hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 \
--hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749
# via flask
jinja2==2.11.2 \
--hash=sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0 \
--hash=sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035
# via flask
markupsafe==1.1.1 \
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be
# via jinja2
niceware==0.2.1 \
--hash=sha256:0f8b192f2a1e800e068474f6e208be9c7e2857664b33a96f4045340de4e5c69c \
--hash=sha256:cf2dc0e1567d36d067c61b32fed0f1b9c4534ed511f9eeead4ba548d03b5c9eb
# via -r requirements.in
psutil==5.8.0 \
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563
# via -r requirements.in
pycparser==2.20 \
--hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \
--hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705
# via cffi
pynacl==1.4.0 \
--hash=sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4 \
--hash=sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4 \
--hash=sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574 \
--hash=sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d \
--hash=sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634 \
--hash=sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25 \
--hash=sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f \
--hash=sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505 \
--hash=sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122 \
--hash=sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7 \
--hash=sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420 \
--hash=sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f \
--hash=sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96 \
--hash=sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6 \
--hash=sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6 \
--hash=sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514 \
--hash=sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff \
--hash=sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80
# via -r requirements.in
pysocks==1.7.1 \
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r requirements.in
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
# via
# -r requirements.in
# streamedrequests
six==1.15.0 \
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced
# via pynacl
stem==1.8.0 \
--hash=sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2
# via -r requirements.in
streamedrequests==1.0.3 \
--hash=sha256:4388ffc0ee94dda719dafc4324b8ddd108cb2231ec59871de79e2592bf4eef0a \
--hash=sha256:ee68417a1522e75c35b1b2d5f3b6f7e76a3a1a6c0ef5e0c573d08307910079d8
# via -r requirements.in
toomanyobjs==1.1.0 \
--hash=sha256:99e27468f9dad19127be9e2fb086b42acd69aed9ad7e63cef74d6e4389be0534
# via -r requirements.in
ujson==4.0.1 \
--hash=sha256:078808c385036cba73cad96f498310c61e9b5ae5ac9ea01e7c3996ece544b556 \
--hash=sha256:0a2e1b211714eb1ec0772a013ec9967f8f95f21c84e8f46382e9f8a32ae781fe \
--hash=sha256:0f412c3f59b1ab0f40018235224ca0cf29232d0201ff5085618565a8a9c810ed \
--hash=sha256:26cf6241b36ff5ce4539ae687b6b02673109c5e3efc96148806a7873eaa229d3 \
--hash=sha256:2b2d9264ac76aeb11f590f7a1ccff0689ba1313adacbb6d38d3b15f21a392897 \
--hash=sha256:4f12b0b4e235b35d49f15227b0a827e614c52dda903c58a8f5523936c233dfc7 \
--hash=sha256:4fe8c6112b732cba5a722f7cbe22f18d405f6f44415794a5b46473a477635233 \
--hash=sha256:51480048373cf97a6b97fcd70c3586ca0a31f27e22ab680fb14c1f22bedbf743 \
--hash=sha256:568bb3e7f035006147af4ce3a9ced7d126c92e1a8607c7b2266007b1c1162c53 \
--hash=sha256:5fe1536465b1c86e32a47113abd3178001b7c2dcd61f95f336fe2febf4661e74 \
--hash=sha256:71703a269f074ff65b9d7746662e4b3e76a4af443e532218af1e8ce15d9b1e7b \
--hash=sha256:7a1545ac2476db4cc1f0f236603ccbb50991fc1bba480cda1bc06348cc2a2bf0 \
--hash=sha256:a5200a68f1dcf3ce275e1cefbcfa3914b70c2b5e2f71c2e31556aa1f7244c845 \
--hash=sha256:a618af22407baeadb3f046f81e7a5ee5e9f8b0b716d2b564f92276a54d26a823 \
--hash=sha256:a79bca47eafb31c74b38e68623bc9b2bb930cb48fab1af31c8f2cb68cf473421 \
--hash=sha256:b87379a3f8046d6d111762d81f3384bf38ab24b1535c841fe867a4a097d84523 \
--hash=sha256:bd4c77aee3ffb920e2dbc21a9e0c7945a400557ce671cfd57dbd569f5ebc619d \
--hash=sha256:c354c1617b0a4378b6279d0cd511b769500cf3fa7c42e8e004cbbbb6b4c2a875 \
--hash=sha256:c604024bd853b5df6be7d933e934da8dd139e6159564db7c55b92a9937678093 \
--hash=sha256:e7ab24942b2d57920d75b817b8eead293026db003247e26f99506bdad86c61b4 \
--hash=sha256:f8a60928737a9a47e692fcd661ef2b5d75ba22c7c930025bd95e338f2a6e15bc
# via -r requirements.in
unpaddedbase32==0.2.0 \
--hash=sha256:4aacee75f8fd6c8cf129842ecba45ca59c11bfb13dae19d86f32b48fa3715403 \
--hash=sha256:b7b780c31d27d55e66abf6c221216a35690ee8892c2daacff7f2528e229bd9c3
# via -r requirements.in
urllib3==1.25.11 \
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e
# via
# -r requirements.in
# requests
watchdog==1.0.2 \
--hash=sha256:016b01495b9c55b5d4126ed8ae75d93ea0d99377084107c33162df52887cee18 \
--hash=sha256:101532b8db506559e52a9b5d75a308729b3f68264d930670e6155c976d0e52a0 \
--hash=sha256:27d9b4666938d5d40afdcdf2c751781e9ce36320788b70208d0f87f7401caf93 \
--hash=sha256:2f1ade0d0802503fda4340374d333408831cff23da66d7e711e279ba50fe6c4a \
--hash=sha256:376cbc2a35c0392b0fe7ff16fbc1b303fd99d4dd9911ab5581ee9d69adc88982 \
--hash=sha256:57f05e55aa603c3b053eed7e679f0a83873c540255b88d58c6223c7493833bac \
--hash=sha256:5f1f3b65142175366ba94c64d8d4c8f4015825e0beaacee1c301823266b47b9b \
--hash=sha256:602dbd9498592eacc42e0632c19781c3df1728ef9cbab555fab6778effc29eeb \
--hash=sha256:68744de2003a5ea2dfbb104f9a74192cf381334a9e2c0ed2bbe1581828d50b61 \
--hash=sha256:85e6574395aa6c1e14e0f030d9d7f35c2340a6cf95d5671354ce876ac3ffdd4d \
--hash=sha256:b1d723852ce90a14abf0ec0ca9e80689d9509ee4c9ee27163118d87b564a12ac \
--hash=sha256:d948ad9ab9aba705f9836625b32e965b9ae607284811cd98334423f659ea537a \
--hash=sha256:e2a531e71be7b5cc3499ae2d1494d51b6a26684bcc7c3146f63c810c00e8a3cc \
--hash=sha256:e7c73edef48f4ceeebb987317a67e0080e5c9228601ff67b3c4062fa020403c7 \
--hash=sha256:ee21aeebe6b3e51e4ba64564c94cee8dbe7438b9cb60f0bb350c4fa70d1b52c2 \
--hash=sha256:f1d0e878fd69129d0d68b87cee5d9543f20d8018e82998efb79f7e412d42154a \
--hash=sha256:f84146f7864339c8addf2c2b9903271df21d18d2c721e9a77f779493234a82b5
# via -r requirements.in
werkzeug==1.0.1 \
--hash=sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43 \
--hash=sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c
# via flask
zope.event==4.5.0 \
--hash=sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 \
--hash=sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330
# via gevent
zope.interface==5.2.0 \
--hash=sha256:05a97ba92c1c7c26f25c9f671aa1ef85ffead6cdad13770e5b689cf983adc7e1 \
--hash=sha256:07d61722dd7d85547b7c6b0f5486b4338001fab349f2ac5cabc0b7182eb3425d \
--hash=sha256:0a990dcc97806e5980bbb54b2e46b9cde9e48932d8e6984daf71ef1745516123 \
--hash=sha256:150e8bcb7253a34a4535aeea3de36c0bb3b1a6a47a183a95d65a194b3e07f232 \
--hash=sha256:1743bcfe45af8846b775086471c28258f4c6e9ee8ef37484de4495f15a98b549 \
--hash=sha256:1b5f6c8fff4ed32aa2dd43e84061bc8346f32d3ba6ad6e58f088fe109608f102 \
--hash=sha256:21e49123f375703cf824214939d39df0af62c47d122d955b2a8d9153ea08cfd5 \
--hash=sha256:21f579134a47083ffb5ddd1307f0405c91aa8b61ad4be6fd5af0171474fe0c45 \
--hash=sha256:27c267dc38a0f0079e96a2945ee65786d38ef111e413c702fbaaacbab6361d00 \
--hash=sha256:299bde0ab9e5c4a92f01a152b7fbabb460f31343f1416f9b7b983167ab1e33bc \
--hash=sha256:2ab88d8f228f803fcb8cb7d222c579d13dab2d3622c51e8cf321280da01102a7 \
--hash=sha256:2ced4c35061eea623bc84c7711eedce8ecc3c2c51cd9c6afa6290df3bae9e104 \
--hash=sha256:2dcab01c660983ba5e5a612e0c935141ccbee67d2e2e14b833e01c2354bd8034 \
--hash=sha256:32546af61a9a9b141ca38d971aa6eb9800450fa6620ce6323cc30eec447861f3 \
--hash=sha256:32b40a4c46d199827d79c86bb8cb88b1bbb764f127876f2cb6f3a47f63dbada3 \
--hash=sha256:3cc94c69f6bd48ed86e8e24f358cb75095c8129827df1298518ab860115269a4 \
--hash=sha256:42b278ac0989d6f5cf58d7e0828ea6b5951464e3cf2ff229dd09a96cb6ba0c86 \
--hash=sha256:495b63fd0302f282ee6c1e6ea0f1c12cb3d1a49c8292d27287f01845ff252a96 \
--hash=sha256:4af87cdc0d4b14e600e6d3d09793dce3b7171348a094ba818e2a68ae7ee67546 \
--hash=sha256:4b94df9f2fdde7b9314321bab8448e6ad5a23b80542dcab53e329527d4099dcb \
--hash=sha256:4c48ddb63e2b20fba4c6a2bf81b4d49e99b6d4587fb67a6cd33a2c1f003af3e3 \
--hash=sha256:4df9afd17bd5477e9f8c8b6bb8507e18dd0f8b4efe73bb99729ff203279e9e3b \
--hash=sha256:518950fe6a5d56f94ba125107895f938a4f34f704c658986eae8255edb41163b \
--hash=sha256:538298e4e113ccb8b41658d5a4b605bebe75e46a30ceca22a5a289cf02c80bec \
--hash=sha256:55465121e72e208a7b69b53de791402affe6165083b2ea71b892728bd19ba9ae \
--hash=sha256:588384d70a0f19b47409cfdb10e0c27c20e4293b74fc891df3d8eb47782b8b3e \
--hash=sha256:6278c080d4afffc9016e14325f8734456831124e8c12caa754fd544435c08386 \
--hash=sha256:64ea6c221aeee4796860405e1aedec63424cda4202a7ad27a5066876db5b0fd2 \
--hash=sha256:681dbb33e2b40262b33fd383bae63c36d33fd79fa1a8e4092945430744ffd34a \
--hash=sha256:6936aa9da390402d646a32a6a38d5409c2d2afb2950f045a7d02ab25a4e7d08d \
--hash=sha256:778d0ec38bbd288b150a3ae363c8ffd88d2207a756842495e9bffd8a8afbc89a \
--hash=sha256:8251f06a77985a2729a8bdbefbae79ee78567dddc3acbd499b87e705ca59fe24 \
--hash=sha256:83b4aa5344cce005a9cff5d0321b2e318e871cc1dfc793b66c32dd4f59e9770d \
--hash=sha256:844fad925ac5c2ad4faaceb3b2520ad016b5280105c6e16e79838cf951903a7b \
--hash=sha256:8ceb3667dd13b8133f2e4d637b5b00f240f066448e2aa89a41f4c2d78a26ce50 \
--hash=sha256:92dc0fb79675882d0b6138be4bf0cec7ea7c7eede60aaca78303d8e8dbdaa523 \
--hash=sha256:9789bd945e9f5bd026ed3f5b453d640befb8b1fc33a779c1fe8d3eb21fe3fb4a \
--hash=sha256:a2b6d6eb693bc2fc6c484f2e5d93bd0b0da803fa77bf974f160533e555e4d095 \
--hash=sha256:aab9f1e34d810feb00bf841993552b8fcc6ae71d473c505381627143d0018a6a \
--hash=sha256:abb61afd84f23099ac6099d804cdba9bd3b902aaaded3ffff47e490b0a495520 \
--hash=sha256:adf9ee115ae8ff8b6da4b854b4152f253b390ba64407a22d75456fe07dcbda65 \
--hash=sha256:aedc6c672b351afe6dfe17ff83ee5e7eb6ed44718f879a9328a68bdb20b57e11 \
--hash=sha256:b7a00ecb1434f8183395fac5366a21ee73d14900082ca37cf74993cf46baa56c \
--hash=sha256:ba32f4a91c1cb7314c429b03afbf87b1fff4fb1c8db32260e7310104bd77f0c7 \
--hash=sha256:cbd0f2cbd8689861209cd89141371d3a22a11613304d1f0736492590aa0ab332 \
--hash=sha256:e4bc372b953bf6cec65a8d48482ba574f6e051621d157cf224227dbb55486b1e \
--hash=sha256:eccac3d9aadc68e994b6d228cb0c8919fc47a5350d85a1b4d3d81d1e98baf40c \
--hash=sha256:efd550b3da28195746bb43bd1d815058181a7ca6d9d6aa89dd37f5eefe2cacb7 \
--hash=sha256:efef581c8ba4d990770875e1a2218e856849d32ada2680e53aebc5d154a17e20 \
--hash=sha256:f057897711a630a0b7a6a03f1acf379b6ba25d37dc5dc217a97191984ba7f2fc \
--hash=sha256:f37d45fab14ffef9d33a0dc3bc59ce0c5313e2253323312d47739192da94f5fd \
--hash=sha256:f44906f70205d456d503105023041f1e63aece7623b31c390a0103db4de17537
# via gevent
# WARNING: The following packages were not pinned, but pip requires them to be
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
# setuptools

View File

@ -1,270 +0,0 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-base-x86.txt requirements-base.in
#
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
# via pynacl
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements-base.in
kasten==3.0.0 \
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
# via onionrblocks
mimcvdf==1.2.1 \
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
# via kasten
msgpack==1.0.4 \
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
# via kasten
onionrblocks==7.0.0 \
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
# via -r requirements-base.in
ordered-set==4.1.0 \
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
# via -r requirements-base.in
psutil==5.9.3 \
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
# via -r requirements-base.in
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
pynacl==1.5.0 \
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
# via onionrblocks
result==0.8.0 \
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
# via -r requirements-base.in
ujson==5.5.0 \
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
# via -r requirements-base.in

View File

@ -1,7 +0,0 @@
psutil==5.9.3
ujson==5.5.0
ordered-set==4.1.0
result==0.8.0
# These two are also by Kevin
filenuke==0.0.0
onionrblocks==7.0.0

View File

@ -0,0 +1 @@
simplenotifications==0.2.18

View File

@ -0,0 +1,8 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-notifications.txt requirements-notifications.in
#
simplenotifications==0.2.18 \
--hash=sha256:b7efd3d834b1922a3279287913d87fe4ef6fad181ca7edf54bfb8f1d973941e0

View File

@ -1,445 +0,0 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-x86-all-plugins.txt requirements-base.in static-data/official-plugins/rpc/requirements.in static-data/official-plugins/tor/requirements.in static-data/official-plugins/wot/requirements.in
#
autocommand==2.2.1 \
--hash=sha256:85d03044c2a1fc1c7844ac41545045927aecde0cbaf8ea28b88e0cd8588ce5d3 \
--hash=sha256:fed420e9d02745821a782971b583c6970259ee0b229be2a0a401e1467a4f170f
# via jaraco-text
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
# via
# -r static-data/official-plugins/wot/requirements.in
# cryptography
# pynacl
cheroot==8.6.0 \
--hash=sha256:366adf6e7cac9555486c2d1be6297993022eff6f8c4655c1443268cca3f08e25 \
--hash=sha256:62cbced16f07e8aaf512673987cd6b1fc5ad00073345e9ed6c4e2a5cc2a3a22d
# via cherrypy
cherrypy==18.8.0 \
--hash=sha256:9b48cfba8a2f16d5b6419cc657e6d51db005ba35c5e3824e4728bb03bbc7ef9b \
--hash=sha256:b56097025dc78a76a59db551b3a82871c6b3a0107b80b12ff759e4c0b3b947ce
# via -r static-data/official-plugins/rpc/requirements.in
cryptography==38.0.1 \
--hash=sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a \
--hash=sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f \
--hash=sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0 \
--hash=sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407 \
--hash=sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7 \
--hash=sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6 \
--hash=sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153 \
--hash=sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750 \
--hash=sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad \
--hash=sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6 \
--hash=sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b \
--hash=sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5 \
--hash=sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a \
--hash=sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d \
--hash=sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d \
--hash=sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294 \
--hash=sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0 \
--hash=sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a \
--hash=sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac \
--hash=sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61 \
--hash=sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013 \
--hash=sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e \
--hash=sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb \
--hash=sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9 \
--hash=sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd \
--hash=sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818
# via secretstorage
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements-base.in
inflect==6.0.0 \
--hash=sha256:0bc1516ec2725e2d8221707a612245093cb6f1cea209cfd8cbd4fc5e96fa6365 \
--hash=sha256:e3b85d65a296843268f35f4136283ad7c012a129375db1529d49b4b01ecb400b
# via jaraco-text
jaraco-classes==3.2.2 \
--hash=sha256:6745f113b0b588239ceb49532aa09c3ebb947433ce311ef2f8e3ad64ebb74594 \
--hash=sha256:e6ef6fd3fcf4579a7a019d87d1e56a883f4e4c35cfe925f86731abc58804e647
# via
# jaraco-collections
# keyring
jaraco-collections==3.5.2 \
--hash=sha256:072b93eb35f9e48508485755534e66a34ef1cc84af291fd27f39b44d4c0dd2c3 \
--hash=sha256:1ca12fa4b7067dfc8d7f791c1a8660d970a2bf2f80536ba0aa5cbb71fe1261f1
# via cherrypy
jaraco-context==4.1.2 \
--hash=sha256:9327d3e6901923e5a7097aa2df4b9c2bc13f845c7672692e3827ebd1b3d67606 \
--hash=sha256:a58e94dd67871639abc091b57d32842449b230777570ef2bcec3dc16b912613e
# via jaraco-text
jaraco-functools==3.5.1 \
--hash=sha256:c8774f73323de42250a659934215da1d899b02c66a6133f1cb79f02a5aff4f38 \
--hash=sha256:d0adcf91710a0853efe9f23a78fad586bf67df572f0d6d8e0fa36d289ae1c1d9
# via
# cheroot
# jaraco-text
# tempora
jaraco-text==3.9.1 \
--hash=sha256:3ca615c4135e151d21206075ec4aface8a2fbc3e68437fe709a6541428a635f9 \
--hash=sha256:d57cd4448a588020318425e04194e897f96fc23b92b82ff9308a24d5cbf2b3fb
# via jaraco-collections
jeepney==0.8.0 \
--hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \
--hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755
# via
# keyring
# secretstorage
json-rpc==1.13.0 \
--hash=sha256:84b45058e5ba95f49c7b6afcf7e03ab86bee89bf2c01f3ad8dd41fe114fc1f84 \
--hash=sha256:def0dbcf5b7084fc31d677f2f5990d988d06497f2f47f13024274cfb2d5d7589
# via -r static-data/official-plugins/rpc/requirements.in
kasten==3.0.0 \
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
# via onionrblocks
keyring==23.9.3 \
--hash=sha256:69732a15cb1433bdfbc3b980a8a36a04878a6cfd7cb99f497b573f31618001c0 \
--hash=sha256:69b01dd83c42f590250fe7a1f503fc229b14de83857314b1933a3ddbf595c4a5
# via -r static-data/official-plugins/wot/requirements.in
mimcvdf==1.2.1 \
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
# via kasten
more-itertools==8.14.0 \
--hash=sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2 \
--hash=sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750
# via
# cheroot
# cherrypy
# jaraco-classes
# jaraco-functools
# jaraco-text
msgpack==1.0.4 \
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
# via kasten
onionrblocks==7.0.0 \
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
# via -r requirements-base.in
ordered-set==4.1.0 \
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
# via -r requirements-base.in
portend==3.1.0 \
--hash=sha256:239e3116045ea823f6df87d6168107ad75ccc0590e37242af0cc1e98c5d224e4 \
--hash=sha256:9e735cee3a5c1961f09e3f3ba6dc498198c2d70b473d98d0d1504b8d1e7a3d61
# via cherrypy
psutil==5.9.3 \
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
# via -r requirements-base.in
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
pydantic==1.10.2 \
--hash=sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42 \
--hash=sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624 \
--hash=sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e \
--hash=sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559 \
--hash=sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709 \
--hash=sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9 \
--hash=sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d \
--hash=sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52 \
--hash=sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda \
--hash=sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912 \
--hash=sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c \
--hash=sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525 \
--hash=sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe \
--hash=sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41 \
--hash=sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b \
--hash=sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283 \
--hash=sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965 \
--hash=sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c \
--hash=sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410 \
--hash=sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5 \
--hash=sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116 \
--hash=sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98 \
--hash=sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f \
--hash=sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644 \
--hash=sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13 \
--hash=sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd \
--hash=sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254 \
--hash=sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6 \
--hash=sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488 \
--hash=sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5 \
--hash=sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c \
--hash=sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1 \
--hash=sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a \
--hash=sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2 \
--hash=sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d \
--hash=sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236
# via inflect
pynacl==1.5.0 \
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
# via
# -r static-data/official-plugins/wot/requirements.in
# onionrblocks
pysocks==1.7.1 \
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r static-data/official-plugins/tor/requirements.in
pytz==2022.2.1 \
--hash=sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197 \
--hash=sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5
# via tempora
result==0.8.0 \
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
# via -r requirements-base.in
secretstorage==3.3.3 \
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99
# via keyring
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
# via cheroot
stem==1.8.1 \
--hash=sha256:81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f
# via -r static-data/official-plugins/tor/requirements.in
tempora==5.0.2 \
--hash=sha256:31fa5bb33b2641026211f23e808eb8bd351901988b167d45f323c8f450ecf211 \
--hash=sha256:e65d32ae68ad772ee738d802689f689b3f883e165e8dadd39aa89ef317b12b99
# via portend
typing-extensions==4.3.0 \
--hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \
--hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6
# via pydantic
ujson==5.5.0 \
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
# via -r requirements-base.in
zc-lockfile==2.0 \
--hash=sha256:307ad78227e48be260e64896ec8886edc7eae22d8ec53e4d528ab5537a83203b \
--hash=sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f
# via cherrypy
# WARNING: The following packages were not pinned, but pip requires them to be
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
# setuptools

View File

@ -1,8 +1,11 @@
PyNaCl==1.5.0
PySocks==1.7.1
stem==1.8.0
unpaddedbase32==0.2.0
niceware==0.2.1
psutil==5.9.1
filenuke==0.0.0
ujson==5.4.0
cffi==1.15.1
onionrblocks==7.0.0
ordered-set==4.1.0
json-rpc==1.13.0
ordered-set==4.1.0

40
requirements.txt Normal file
View File

@ -0,0 +1,40 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
#
cffi==1.15.1
# via
# -r requirements.in
# pynacl
filenuke==0.0.0
# via -r requirements.in
kasten==3.0.0
# via onionrblocks
mimcvdf==1.2.1
# via kasten
msgpack==1.0.3
# via kasten
niceware==0.2.1
# via -r requirements.in
onionrblocks==7.0.0
# via -r requirements.in
ordered-set==4.1.0
# via -r requirements.in
psutil==5.9.1
# via -r requirements.in
pycparser==2.19
# via cffi
pynacl==1.5.0
# via
# -r requirements.in
# onionrblocks
pysocks==1.7.1
# via -r requirements.in
stem==1.8.0
# via -r requirements.in
ujson==5.4.0
# via -r requirements.in
unpaddedbase32==0.2.0
# via -r requirements.in

150
run-onionr-node.py Executable file
View File

@ -0,0 +1,150 @@
#!/usr/bin/env python3
import argparse
import os
from threading import Thread
from time import sleep
from subprocess import DEVNULL
import ujson
from psutil import Popen
from psutil import Process
import sys
script_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(script_dir + '/src/')
import onionrvalues
sub_script = script_dir + '/' + onionrvalues.SCRIPT_NAME
parser = argparse.ArgumentParser()
parser.add_argument(
"--bind-address", help="Address to bind to. Be very careful with non-loopback",
type=str, default="")
parser.add_argument(
"--port", help="Port to bind to, must be available and possible",
type=int, default=0)
parser.add_argument(
"--use-bootstrap-file", help="Use bootstrap node list file",
type=int, default=1)
parser.add_argument(
"--show-stats", help="Display curses output of Onionr stats",
type=int, default=0)
parser.add_argument(
"--onboarding", help="Use Onionr onboarding (if first load)",
type=int, default=1)
parser.add_argument(
"--security-level", help="Set Onionr security level",
type=int, default=0)
parser.add_argument(
'--open-ui', help='Open onionr web ui after started',
type=int, default=1)
parser.add_argument(
'--random-localhost-ip', help='bind to random localhost IP for extra security',
type=int, default=1)
parser.add_argument(
'--use-tor', help='Use Tor transport',
type=int, default=1)
parser.add_argument(
'--private-key', help='Use existing private key',
type=str, default=0)
parser.add_argument(
'--animated-background', help='Animated background on webui index. Just for looks.',
type=int, default=0)
parser.add_argument(
'--keep-log-on-exit', help='Onionr can keep or delete its log file on exit',
type=int, default=0)
parser.add_argument(
'--use-upload-mixing', help='Re-upload blocks uploaded to us. Slow but more secure',
type=int, default=0)
parser.add_argument(
'--dev-mode',
help='Developer mode makes restarting and testing Onionr less tedious during development',
type=int, default=0)
parser.add_argument(
'--disable-plugin-list',
help='plugins to disable by name, separate with commas',
type=str, default='chat'
)
parser.add_argument(
'--store-plaintext',
help='store plaintext blocks or not. note that encrypted blocks may not really be encrypted, but we cannot detect that',
type=int, default=1
)
args = parser.parse_args()
p = Popen([sub_script, 'version'])
p.wait()
print("Configuring Onionr before starting daemon")
from filepaths import config_file, keys_file
from coredb import blockmetadb
import onionrcrypto
with open(config_file, 'r') as cf:
config = ujson.loads(cf.read())
if args.private_key:
priv = args.private_key
pub = onionrcrypto.cryptoutils.get_pub_key_from_priv(priv)
with open(keys_file, "a") as f:
f.write(',' + pub.decode() + ',' + priv)
config['general']['public_key'] = pub
config['plugins']['disabled'] = args.disable_plugin_list.split(',')
config['general']['dev_mode'] = False
config['general']['store_plaintext_blocks'] = True
config['general']['use_bootstrap_list'] = True
config['transports']['tor'] = True
config['general']['bind_port'] = 0 # client api server port
config['general']['bind_address'] = '' # client api server address
if args.bind_address:
config['general']['bind_address'] = args.bind_address
if args.port:
config['client']['client']['port'] = args.port
if not args.use_bootstrap_file:
config['general']['use_bootstrap_list'] = False
if not args.store_plaintext:
config['general']['store_plaintext_blocks'] = False
if args.dev_mode:
config['general']['dev_mode'] = True
if not args.onboarding:
config['onboarding']['done'] = True
if not args.random_localhost_ip:
config['general']['random_bind_ip'] = False
if not args.use_tor:
config['transports']['tor'] = False
if not args.animated_background:
config['ui']['animated_background'] = False
if args.keep_log_on_exit:
config['log']['file']['remove_on_exit'] = True
else:
config['log']['file']['remove_on_exit'] = False
config['general']['upload_mixing'] = False
if args.use_upload_mixing:
config['general']['upload_mixing'] = True
config['general']['display_header'] = False
config['general']['security_level'] = args.security_level
with open(config_file, 'w') as cf:
cf.write(ujson.dumps(config, reject_bytes=False))
if args.open_ui:
p = Popen([sub_script, 'start'])
sleep(2)
Popen([sub_script, 'openhome'])
else:
p = Popen([sub_script, 'start'])
p.wait()

51
run-onionr-node.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/sh
set -x
ORIG_ONIONR_RUN_DIR=`pwd`
export ORIG_ONIONR_RUN_DIR
cd "$(dirname "$0")"
if [[ -n "$ONIONR_DOCKER" ]]; then
[[ -f "/privkey" ]] && privkey_opt="--private-key /privkey"
[[ -n "$ONIONR_ONBOARDING" ]] || ONIONR_ONBOARDING=0
[[ -n "$ONIONR_OPEN_UI" ]] || ONIONR_OPEN_UI=0
[[ -n "$ONIONR_RANDOM_LOCALHOST_IP" ]] || ONIONR_RANDOM_LOCALHOST_IP=0
[[ -n "$ONIONR_BIND_ADDRESS" ]] || ONIONR_BIND_ADDRESS=0.0.0.0
[[ -n "$ONIONR_PORT" ]] || ONIONR_PORT=8080
fi
[[ -n "$ONIONR_PRIVATE_KEY_FILE" ]] && privkey_opt="--private-key $ONIONR_PRIVATE_KEY_FILE"
[[ -n "$ONIONR_USE_BOOTSTRAP_FILE" ]] && bootstrap_opt="--use-bootstrap-file $ONIONR_USE_BOOTSTRAP_FILE"
[[ -n "$ONIONR_SHOW_STATS" ]] && show_stats_opt="--show-stats $ONIONR_SHOW_STATS"
[[ -n "$ONIONR_ONBOARDING" ]] && onboarding_opt="--onboarding $ONIONR_ONBOARDING"
[[ -n "$ONIONR_SECURITY_LEVEL" ]] && security_level_opt="--security-level $ONIONR_SECURITY_LEVEL"
[[ -n "$ONIONR_OPEN_UI" ]] && open_ui_opt="--open-ui $ONIONR_OPEN_UI"
[[ -n "$ONIONR_RANDOM_LOCALHOST_IP" ]] && random_localhost_ip_opt="--random-localhost-ip $ONIONR_RANDOM_LOCALHOST_IP"
[[ -n "$ONIONR_USE_TOR" ]] && use_tor_opt="--use-tor $ONIONR_USE_TOR"
[[ -n "$ONIONR_ANIMATED_BACKGROUND" ]] && animated_background_opt="--animated-background $ONIONR_ANIMATED_BACKGROUND"
[[ -n "$ONIONR_KEEP_LOG" ]] && keep_log_opt="--keep-log-on-exit $ONIONR_KEEP_LOG"
[[ -n "$ONIONR_USE_UPLOAD_MIXING" ]] && use_upload_mixing_opt="--use-upload-mixing $ONIONR_USE_UPLOAD_MIXING"
[[ -n "$ONIONR_DEV_MODE" ]] && dev_mode_opt="--dev-mode $ONIONR_DEV_MODE"
[[ -n "$ONIONR_DISABLE_PLUGIN_LIST" ]] && disable_plugin_list_opt=" --disable-plugin-list $ONIONR_DISABLE_PLUGIN_LIST"
[[ -n "$ONIONR_STORE_PLAINTEXT" ]] && store_plaintext_opt="--store-plaintext $ONIONR_STORE_PLAINTEXT"
[[ -n "$ONIONR_BIND_ADDRESS" ]] && bind_address_opt="--bind-address $ONIONR_BIND_ADDRESS"
[[ -n "$ONIONR_PORT" ]] && port_opt="--port $ONIONR_PORT"
python3 run-onionr-node.py \
$privkey_opt \
$bootstrap_opt \
$show_stats_opt \
$onboarding_opt \
$security_level_opt \
$open_ui_opt \
$random_localhost_ip_opt \
$use_tor_opt \
$animated_background_opt \
$keep_log_opt \
$use_upload_mixing_opt \
$dev_mode_opt \
$disable_plugin_list_opt \
$store_plaintext_opt \
$bind_address_opt \
$port_opt \
"$@"

33
sandboxed-onionr.py Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
import os, sys
import tempfile, shutil
import stat
env_var = "firejailed-onionr"
def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src):
if item in (".git", ".vscode", ".github"):
continue
s = os.path.join(src, item)
d = os.path.join(dst, item)
if os.path.isdir(s):
shutil.copytree(s, d, symlinks, ignore)
else:
shutil.copy2(s, d)
env_var = "firejailed-onionr"
directory = os.path.dirname(os.path.realpath(sys.argv[0]))
if not os.getenv(env_var):
temp_dir = tempfile.mkdtemp()
print(temp_dir)
copytree(directory, temp_dir)
os.system(f"firejail --env={env_var}={temp_dir} --private={temp_dir} python3 ./sandboxed-onionr.py")
sys.exit(0)
os.system(f"python3 -m pip install -r ./requirements.txt --user")
os.system(f"./onionr.sh start &")

View File

@ -1 +1,7 @@
This directory contains useful scripts and utilities that don't make sense to include as official Onionr features.
passphrase-generator.py: very simple utility to generate and print a strong passphrase to stdout. 256 bits of entropy by default.
enable-dev-config.py/disable-dev-config.py: enable/disable dev default config setup
block-spammer.py: attack tool for spamming blocks
announce-attack.py: flood a node with false nodes
run-unit-test-by-name: runs a unit test (no browser, runtime or intgegration test) by name

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Craft and send requests to the local client API"""
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import atexit
import readline
histfile = os.path.join(os.path.expanduser("~"), ".onionr_history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
from onionrutils.localcommand import local_command
from onionrutils.localcommand import get_hostname
try:
print('API file found, probably running on ' + get_hostname())
except TypeError:
print('Onionr not running')
sys.exit(1)
print('1. get request (default)')
print('2. post request')
choice = input(">").lower().strip()
post = False
post_data = {}
json = False
endpoint = input("URL Endpoint: ")
data = input("Data url param: ")
if choice in ("2", "post", "post request"):
post = True
print("Enter post data")
post_data = input()
if post_data:
print("Is this JSON?")
json = input("y/n").lower().strip()
if json == "y":
json = True
ret = local_command(endpoint, data=data, post=post, post_data=post_data, is_json=json)
print("Response: \n", ret)

View File

@ -11,9 +11,12 @@ conf['tor']['existing_control_port'] = 0
conf['tor']['existing_control_password'] = ""
conf['tor']['existing_socks_port'] = 0
conf['general']['dev_mode'] = False
conf['general']['insert_deniable_blocks'] = True
conf['general']['random_bind_ip'] = True
conf['general']['display_header'] = True
conf['general']['security_level'] = 0
conf['general']['use_bootstrap_list'] = True
conf['onboarding']['done'] = False
conf['general']['minimum_block_pow'] = 5
conf['general']['minimum_send_pow'] = 5

View File

@ -10,6 +10,7 @@ conf = json.load(open('static-data/default_config.json', 'r'))
block_pow = int(input("Block POW level:"))
conf['general']['security_level'] = int(input("Security level:"))
conf['transports']['tor'] = False
if input('Use Tor? y/n').lower() == 'y':
conf['transports']['tor'] = True
@ -19,11 +20,15 @@ if input('Use Tor? y/n').lower() == 'y':
conf['tor']['existing_control_password'] = input("Tor pass:")
conf['tor']['existing_socks_port'] = int(input("Existing socks port:"))
conf['general']['dev_mode'] = True
conf['general']['insert_deniable_blocks'] = False
conf['general']['random_bind_ip'] = False
conf['onboarding']['done'] = True
conf['general']['minimum_block_pow'] = block_pow
conf['general']['minimum_send_pow'] = block_pow
conf['general']['use_bootstrap_list'] = False
if input("Use bootstrap list? y/n").lower() == 'y':
conf['general']['use_bootstrap_list'] = True
conf['log']['file']['remove_on_exit'] = False
conf['ui']['animated_background'] = False
if input('Stat reporting? y/n') == 'y':

41
scripts/generate-onions.py Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import sys
import os
import stem
from stem import process
from stem.control import Controller
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
try:
sys.argv[1]
except IndexError:
sys.exit(1)
tor_process = process.launch_tor_with_config(
completion_percent=0,
config = {
'ControlPort': '2778',
'DisableNetwork': '1',
'Log': [
'NOTICE stdout',
'ERR file /tmp/tor_error_log',
],
},
)
with Controller.from_port('127.0.0.1', 2778) as controller:
controller.authenticate()
for i in range(1024, 1024 + int(sys.argv[1])):
hs = controller.create_ephemeral_hidden_service(
{80: i},
key_type='NEW',
key_content='ED25519-V3',
await_publication=False,
detached=True)
print(hs.service_id + ".onion")
controller.remove_ephemeral_hidden_service(hs.service_id)
tor_process.kill()

21
scripts/passphrase-generator.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
"""Generate a 16 word passphase with 256 bits of entropy.
Specify true to reduce to 128 bits"""
import sys
import niceware
byte_count = 32 # 256 bits of entropy with niceware
arg = False
try:
arg = sys.argv[1].lower()
if arg == 'true':
byte_count = 16
except IndexError: pass
print(' '.join(niceware.generate_passphrase(byte_count)))

50
scripts/remote-ui.py Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Craft and send requests to the local client API"""
import sys
import os
import time
from threading import Thread
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import filepaths
import config
config.reload()
with open(filepaths.private_API_host_file, 'r') as host:
hostname = host.read()
port = config.get("client.client.port", 0)
if not port:
print("Could not get port for Onionr UI. Try again")
sys.exit(1)
torrc = f"""
HiddenServiceDir remote-onionr-hs
HiddenServicePort 80 {hostname}:{port}
"""
with open("remote-onionr-torrc", "w") as torrc_f:
torrc_f.write(torrc)
def show_onion():
while True:
time.sleep(1)
try:
with open("remote-onionr-hs/hostname", "r") as f:
o = f.read()
print("UI Onion (Keep secret):", o)
config.set("ui.public_remote_enabled", True)
config.set("ui.public_remote_hosts", [o])
config.save()
break
except FileNotFoundError:
pass
Thread(target=show_onion, daemon=True).start()
os.system("tor -f remote-onionr-torrc")

16
scripts/show-blocks.py Normal file
View File

@ -0,0 +1,16 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from coredb.blockmetadb import get_block_list
from onionrblocks.onionrblockapi import Block
for bl in get_block_list():
bl_obj = Block(bl, decrypt=False)
b_type = bl_obj.getType()
if not b_type:
b_type = "encrypted"
print(bl + " - " + str(bl_obj.date) + " - " + b_type)

40
scripts/sybil-attack.py Normal file
View File

@ -0,0 +1,40 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from onionrutils import stringvalidators
from onionrutils import basicrequests
from stem.control import Controller
onionr_ip = input("onionr ip address: ")
onionr_port = int(input("Enter onionr public api port: "))
controller = Controller.from_port('127.0.0.1', int(input("Enter tor controller port: ")))
controller.authenticate()
node = input("Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues: ")
assert stringvalidators.validate_transport(node)
socks = input("Socks:")
adders = set([])
for i in range(int(input("Sybil addresses: "))):
response = controller.create_ephemeral_hidden_service({80: f'{onionr_ip}:{onionr_port}'}, await_publication=True)
#print(i, response.service_id)
adders.add(response.service_id)
for x in adders:
x += '.onion'
print(f"Introducing {x} to {node}")
basicrequests.do_post_request(
f'http://{node}/announce',
data = {'node': x},
port=socks)

12
scripts/testblock.py Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env python3
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import onionrblocks
expire = 600
print(onionrblocks.insert(data=os.urandom(32), expire=expire))

View File

@ -15,16 +15,15 @@ try:
except ImportError:
pass
import os
import cProfile
import threading
onionr_profiling = os.getenv("ONIONR_PROFILING", False)
import sys
try:
import sqlite3
except ModuleNotFoundError:
sys.stderr.write(
'Error, Onionr requires Sqlite3-enabled Python.\n' +
'https://stackoverflow.com/a/1875095\n')
sys.exit(1)
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -44,29 +43,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import locale # noqa
locale.setlocale(locale.LC_ALL, '') # noqa
import traceback
import signal
def sigusr_stacktrace(signum, frame):
"""Print stacktrace on SIGUSR1"""
stack_trace_file = os.getenv('ONIONR_STACK_TRACE_FILE', False)
for th in threading.enumerate():
if stack_trace_file:
with open(stack_trace_file, 'a') as f:
f.write(f'Thread: {th.name}')
f.write('-' * 44 + '')
traceback.print_stack(sys._current_frames()[th.ident], file=f)
else:
print(f'Thread: {th.name}')
print('-' * 44)
traceback.print_stack(sys._current_frames()[th.ident])
#print(traceback.format_stack(frame))
signal.signal(signal.SIGUSR1, sigusr_stacktrace)
# Importing initailzes logging
from logger import log as logging
ran_as_script = False
if __name__ == "__main__": ran_as_script = True
@ -97,6 +73,7 @@ if sys.version_info[0] == 2 or sys.version_info[1] < min_ver:
from utils import createdirs
createdirs.create_dirs()
import bigbrother # noqa
from onionrcommands import parser # noqa
from onionrplugins import onionrevents as events # noqa
@ -106,21 +83,23 @@ import config # noqa
from utils import identifyhome # noqa
import filepaths # noqa
if config.get('advanced.security_auditing', True):
try:
bigbrother.enable_ministries()
except onionrexceptions.PythonVersion:
pass
def onionr_main():
"""Onionr entrypoint, start command processor
Entrypoint for daemon is commands/daemonlaunch/__init__.py
"""
events.event('beforecmdparsing', threaded=False)
parser.register()
if ran_as_script:
if onionr_profiling:
cProfile.run('onionr_main()')
else:
onionr_main()
onionr_main()
config.reload()

View File

@ -3,11 +3,10 @@
Processes interpreter hook events to detect security leaks
"""
import sys
import os
from typing import Iterable
from logger import log as logging
from onionrexceptions import PythonVersion
from . import ministry
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,11 +21,15 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
import ministry
plugin_name = 'bigbrother'
PLUGIN_VERSION = '0.0.0'
def _auditing_supported():
try:
sys.audit
sys.addaudithook
except AttributeError:
raise PythonVersion('Auditing not supported interpreter')
def sys_hook_entrypoint(event, info):
"""Entrypoint for big brother sys auditors."""
@ -44,10 +47,5 @@ def sys_hook_entrypoint(event, info):
def enable_ministries(disable_hooks: Iterable = None):
"""Enable auditors."""
disable_hooks = disable_hooks or []
_auditing_supported() # raises PythonVersion exception if <3.8
sys.addaudithook(sys_hook_entrypoint)
def on_init(api, data=None):
enable_ministries()
logging.info(
"Big brother enabled, blocking unsafe Python code.")

View File

@ -4,7 +4,7 @@ Ensure sockets don't get made to non localhost
"""
import ipaddress
from logger import log as logging
import logger
from onionrexceptions import NetworkLeak
"""
This program is free software: you can redistribute it and/or modify
@ -37,12 +37,12 @@ def detect_socket_leaks(socket_event):
try:
ip_address = ipaddress.ip_address(ip_address)
except ValueError:
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
raise \
NetworkLeak('Conn to host/non local IP, this is a privacy issue!')
# Validate that the IP is localhost ipv4
if not ip_address.is_loopback and not ip_address.is_multicast \
and not ip_address.is_private:
logging.warn(f'Conn made to {ip_address} outside of Tor/similar')
logger.warn(f'Conn made to {ip_address} outside of Tor/similar')
raise NetworkLeak('Conn to non local IP, this is a privacy concern!')

View File

@ -3,7 +3,7 @@
Log (not block) read/write of non-user data files and non-python lib files
"""
from utils.identifyhome import identify_home
from logger import log as logging
import logger
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -33,4 +33,4 @@ def detect_disk_access(info):
if identify_home() not in info[0]:
if 'proc' not in info[0]: # if it is, it is onionr stats
logging.warn(f'[DISK MINISTRY] {info}')
logger.warn(f'[DISK MINISTRY] {info}')

View File

@ -0,0 +1,87 @@
"""Onionr - Private P2P Communication.
Prevent eval/exec/os.system and log it
"""
import base64
import platform
import logger
from utils import identifyhome
from onionrexceptions import ArbitraryCodeExec
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
untrusted_exec = True
def block_system(cmd):
"""Prevent os.system except for whitelisted commands+contexts."""
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn(f'POSSIBLE EXPLOIT: shell command not in whitelist: {cmd}')
raise ArbitraryCodeExec('os.system command not in whitelist')
def block_exec(event, info):
"""Prevent arbitrary code execution in eval/exec and log it."""
# because libraries have stupid amounts of compile/exec/eval,
# We have to use a whitelist where it can be tolerated
# Generally better than nothing, not a silver bullet
if untrusted_exec:
return
whitelisted_code = [
'netrc.py',
'shlex.py',
'gzip.py',
'<werkzeug routing>',
'werkzeug/test.py',
'multiprocessing/popen_fork.py',
'multiprocessing/util.py',
'multiprocessing/connection.py',
'multiprocessing/queues.py',
'multiprocessing/synchronize.py',
'onionrutils/escapeansi.py',
'stem/connection.py',
'stem/response/add_onion.py',
'stem/response/authchallenge.py',
'stem/response/getinfo.py',
'stem/response/getconf.py',
'stem/response/mapaddress.py',
'stem/response/protocolinfo.py',
'apport/__init__.py',
'apport/report.py'
]
whitelisted_source = [
'ZABaAGQBZAJsAW0CWgIBAHoGZAFkA2wDWgRXAG4LBABlBXkZAQABAAEAZARaBlkAbgN3AGQFWgZkAWQGbAdtCFoIAQBkAWQDbAlaCWQBZAdsCm0LWgwBAAkAZQmgDWQIZAWhAnM1ZARaBmUIgwBkCRcAWg5kEmQMZQ9kDWUPZgRkDmQPhAVaEGQTZBBkEYQBWhFkA1MA',
'RwBkAGQBhABkAYMCWgBkAlMA',
'ZABaAGQBZAJsAVoBZAFkAmwCWgJkAWQCbANaA2QBZAJsBFoEZAFkAmwFWgVkAWQCbAZaBmQBZAJsB1oIZAFkAmwJWghkAWQCbApaCGQBZAJsC1oIZANaDGQEWg1kBWQCZAJkBmQCZQ1kB2QIZAJmCWQJZAqEAVoOZAVkBmQCZQ1kB2QIZgZkC2QMhAFaD2QCUwA=',
'ZABaAGQBZAJsAVoBZAFkAmwCWgJkAWQCbANaA2QBZAJsBFoEZAFkAmwFWgVkAWQCbAZaBmQBZAJsB1oIZAFkAmwJWghkAWQCbApaCGQBZANsC20MWgxtDVoNbQ5aDm0PWg9tEFoQbRFaEQEAZARaEmQFWhNkBmQCZAJkB2QCZRNkCGQJZAJmCWQKZRRkC2UPZRBlFBkAGQBkDGUPZRQZAGQNZRVkDmUPZQ1lFGcBZAJmAhkAGQBkD2UVZBBlFmQRZRZkEmUPZRQZAGQTZQRqF2YUZBRkFYQFWhhkBmQHZAJlE2QIZAlmBmQWZQ5lFGURZRRlEGUUGQBmAhkAZgIZAGQKZRRkDWUVZA5lD2UNZRRnAWQCZgIZABkAZA9lFWQQZRZkEWUWZBNlBGoXZhBkF2QYhAVaGWQCUwA='
]
home = identifyhome.identify_home()
code_b64 = base64.b64encode(info[0].co_code).decode()
if code_b64 in whitelisted_source:
return
for source in whitelisted_code:
if info[0].co_filename.endswith(source):
return
if 'plugins/' in info[0].co_filename:
return
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename)
logger.warn('Prevented exec/eval. Report this with the sample below')
logger.warn(f'{event} code in base64 format: {code_b64}')
raise ArbitraryCodeExec("Arbitrary code (eval/exec) detected.")

View File

@ -1,7 +1,6 @@
from typing import Callable, Generator, List
from onionrblocks import Block
from onionrplugins import onionrevents
import db
@ -16,9 +15,8 @@ block_storage_observers: List[Callable] = []
def add_block_to_db(block: Block):
onionrevents.event('before_block_db_add', block, threaded=False)
db.set_if_new(block_db_path, block.id, block.raw) # Raises db.DuplicateKey if dupe
onionrevents.event('after_block_db_add', block, threaded=False)
# Raises db.DuplicateKey if dupe
db.set_if_new(block_db_path, block.id, block.raw)
def has_block(block_hash):

View File

@ -2,7 +2,7 @@ from typing import Set
from onionrblocks import Block
from logger import log as logging
import logger
from .deleteblock import delete_block
from .getblocks import get_blocks_after_timestamp
@ -18,7 +18,7 @@ def clean_block_database():
Block(block.id, block.raw, auto_verify=True)
except ValueError: # block expired
remove_set.add(block)
if len(remove_set):
logging.info(f"Cleaning {len(remove_set)} blocks")
logger.info(f"Cleaning {len(remove_set)} blocks", terminal=True)
[i for i in map(delete_block, remove_set)]

View File

@ -6,12 +6,7 @@ from onionrblocks import Block
from .dbpath import block_db_path
def get_blocks_by_type(block_type: str) -> "Generator[Block]":
try:
block_type = block_type.decode('utf-8')
except AttributeError:
pass
block_db = db.get_db_obj(block_db_path, 'u')
for block_hash in db.list_keys(block_db_path):
block = Block(block_hash, block_db[block_hash], auto_verify=False)
@ -30,4 +25,4 @@ def get_blocks_after_timestamp(
if block_type == block.type:
yield block
else:
yield block
yield block

View File

@ -6,9 +6,10 @@ import os
from json import JSONDecodeError
import ujson as json
from logger import log as logging
import logger
import filepaths
from . import onboarding
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -106,7 +107,7 @@ def save():
with open(get_config_file(), 'w', encoding="utf8") as configfile:
json.dump(get_config(), configfile, indent=2)
except JSONDecodeError:
logging.warn('Failed to write to configuration file.')
logger.warn('Failed to write to configuration file.')
def reload():
@ -117,7 +118,7 @@ def reload():
set_config(json.loads(configfile.read()))
except (FileNotFoundError, JSONDecodeError) as e:
pass
#logging.debug('Failed to parse configuration file.')
#logger.debug('Failed to parse configuration file.')
def get_config():

79
src/config/onboarding.py Normal file
View File

@ -0,0 +1,79 @@
"""Onionr - Private P2P Communication.
Setup config from onboarding choices
"""
from pathlib import Path
from typing import Union
from filepaths import onboarding_mark_file
from onionrtypes import JSONSerializable
from onionrtypes import OnboardingConfig
import config
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _get_val_or_none(json: dict, key: str) -> Union[None, JSONSerializable]:
try:
return json['configInfo'][key]
except KeyError:
return None
def set_config_from_onboarding(config_settings: OnboardingConfig):
get = _get_val_or_none
config.reload()
if get(config_settings, 'optimize'):
config.set('ui.animated_background', False)
config.set('general.insert_deniable_blocks', False)
if get(config_settings, 'stateTarget') or not get(config_settings,
'networkContrib'):
config.set('general.security_level', 1)
if get(config_settings, 'localThreat'):
config.set('general.security_level', 3)
config.set('transports.lan', False)
config.set('ui.theme', 'light')
if get(config_settings, 'useDark'):
config.set('ui.theme', 'dark')
disabled = config.get('plugins.disabled', [])
if not get(config_settings, 'circles') or \
config.get('general.security_level') > 0:
disabled.append('flow')
if not get(config_settings, 'mail'):
disabled.append('pms')
config.set('plugins.disabled', disabled)
config.set('general.store_plaintext_blocks',
get(config_settings, 'plainContrib'))
config.set('onboarding.done', True, savefile=True)
def set_onboarding_finished():
"""Create the onboarding completed setting file"""
Path(onboarding_mark_file).touch()
def is_onboarding_finished() -> bool:
return True

1
src/coredb/__init__.py Normal file
View File

@ -0,0 +1 @@
from . import keydb

9
src/coredb/dbfiles.py Normal file
View File

@ -0,0 +1,9 @@
from utils import identifyhome
import filepaths
home = identifyhome.identify_home()
if not home.endswith('/'): home += '/'
address_info_db = '%saddress.db' % (home,)
user_id_info_db = '%susers.db' % (home,)
forward_keys_db = '%sforward-keys.db' % (home,)
blacklist_db = '%sblacklist.db' % (home,)

View File

@ -0,0 +1 @@
from . import addkeys, listkeys, removekeys, userinfo

View File

@ -0,0 +1,55 @@
"""Onionr - Private P2P Communication.
add user keys or transport addresses
"""
import sqlite3
from onionrutils import stringvalidators
from . import listkeys
from .. import dbfiles
import onionrcrypto
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def add_pub_key(peerID, name=''):
"""Add a public key to the key database (misleading function name)."""
if peerID in listkeys.list_pub_keys() or peerID == onionrcrypto.pub_key:
raise ValueError("specified id is already known")
# This function simply adds a peer to the DB
if not stringvalidators.validate_pub_key(peerID):
return False
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
hashID = ""
c = conn.cursor()
t = (peerID, name, 'unknown', hashID, 0)
for i in c.execute("SELECT * FROM peers WHERE id = ?;", (peerID,)):
try:
if i[0] == peerID:
conn.close()
return False
except ValueError:
pass
except IndexError:
pass
c.execute('INSERT INTO peers (id, name, dateSeen, hashID, trust) VALUES(?, ?, ?, ?, ?);', t)
conn.commit()
conn.close()
return True

View File

@ -0,0 +1,63 @@
"""
Onionr - Private P2P Communication
get lists for user keys
"""
import sqlite3
import logger
from onionrutils import epoch
import onionrvalues
from .. import dbfiles
from . import userinfo
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def list_pub_keys(randomOrder=True, getPow=False, trust=0):
"""
Return a list of public keys (misleading function name)
randomOrder determines if the list should be in a random order
trust sets the minimum trust to list
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
payload = ''
if trust not in (0, 1, 2):
logger.error('Tried to select invalid trust.')
return
if randomOrder:
payload = 'SELECT * FROM peers WHERE trust >= ? ORDER BY RANDOM();'
else:
payload = 'SELECT * FROM peers WHERE trust >= ?;'
peer_list = []
for i in c.execute(payload, (trust,)):
try:
if len(i[0]) != 0:
if getPow:
peer_list.append(i[0] + '-' + i[1])
else:
peer_list.append(i[0])
except TypeError:
pass
conn.close()
return peer_list

View File

@ -0,0 +1,43 @@
"""
Onionr - Private P2P Communication
Remove a transport address but don't ban them
"""
import sqlite3
from onionrplugins import onionrevents as events
from onionrutils import stringvalidators
from onionrutils import mnemonickeys
from .. import dbfiles
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def remove_user(pubkey: str)->bool:
"""Remove a user from the user database"""
pubkey = mnemonickeys.get_base32(pubkey)
if stringvalidators.validate_pub_key(pubkey):
conn = sqlite3.connect(
dbfiles.user_id_info_db,
timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
t = (pubkey,)
c.execute('Delete from peers where id=?;', t)
conn.commit()
conn.close()
return True
else:
return False

View File

@ -0,0 +1,74 @@
"""
Onionr - Private P2P Communication
get or set information about a user id
"""
import sqlite3
from .. import dbfiles
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def get_user_info(peer, info):
"""
Get info about a peer from their database entry
id text 0
name text, 1
adders text, 2
dateSeen not null, 3
trust int 4
hashID text 5
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
command = (peer,)
infoNumbers = {'id': 0, 'name': 1, 'adders': 2, 'dateSeen': 3, 'trust': 4, 'hashID': 5}
info = infoNumbers[info]
iterCount = 0
retVal = ''
for row in c.execute('SELECT * FROM peers WHERE id=?;', command):
for i in row:
if iterCount == info:
retVal = i
break
else:
iterCount += 1
conn.close()
return retVal
def set_peer_info(peer, key, data):
"""
Update a peer for a key
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
command = (data, peer)
if key not in ('id', 'name', 'pubkey', 'forwardKey', 'dateSeen', 'trust'):
raise ValueError("Got invalid database key when setting peer info")
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
conn.commit()
conn.close()
set_user_info = set_peer_info

View File

@ -7,8 +7,36 @@ app_root = os.path.dirname(os.path.realpath(__file__)) + '/../../'
gossip_server_socket_file = home + 'gossip-server.sock'
usage_file = home + 'disk-usage.txt'
contacts_location = home + 'contacts/'
public_API_host_file = home + 'public-host.txt'
private_API_host_file = home + 'private-host.txt'
bootstrap_file_location = 'static-data/bootstrap-nodes.txt'
data_nonce_file = home + 'block-nonces.dat'
forward_keys_file = home + 'forward-keys.db'
cached_storage = home + 'cachedstorage.dat'
export_location = home + 'block-export/'
upload_list = home + 'upload-list.json'
config_file = home + 'config.json'
daemon_mark_file = home + '/daemon-true.txt'
lock_file = home + 'onionr.lock'
pid_file = home + 'onionr.pid'
site_cache = home + 'onionr-sites.txt'
tor_hs_loc = home + 'hs/'
tor_hs_address_file = home + 'hs/hostname'
data_nonce_file = home + 'block-nonces.dat'
keys_file = home + 'keys.txt'
onboarding_mark_file = home + 'onboarding-completed'
log_file = home + 'onionr.log'
ephemeral_services_file = home + 'ephemeral-services.list'
restarting_indicator = home + "is-restarting"
block_database = home + "blocks.db"

View File

@ -1,7 +1,6 @@
import threading
from time import sleep
from typing import TYPE_CHECKING, Set, Tuple
from logger import log as logging
if TYPE_CHECKING:
from ordered_set import OrderedSet
@ -12,6 +11,7 @@ if TYPE_CHECKING:
from onionrthreads import add_onionr_thread
import onionrplugins
import logger
from .connectpeer import connect_peer
from .client import start_gossip_client
@ -56,4 +56,4 @@ def start_gossip_threads():
sleep(60)
if len(gossip_peer_set):
return
logging.error("Could not connect to any peers :(")
logger.error("Could not connect to any peers :(", terminal=True)

View File

@ -21,7 +21,7 @@ if TYPE_CHECKING:
from ..peer import Peer
from ordered_set import OrderedSet
from logger import log as logging
import logger
import config
import onionrplugins
from ..commands import GossipCommands
@ -59,22 +59,22 @@ def block_queue_processing():
while not len(gossip_peer_set):
sleep(1)
sleep(0.2)
if dandelion_phase.remaining_time() <= 15:
#logging.debug("Sleeping")
#logger.debug("Sleeping", terminal=True)
sleep(dandelion_phase.remaining_time())
if dandelion_phase.is_stem_phase() and config.get('security.dandelion.enabled', True):
logging.debug("Entering stem phase")
logger.debug("Entering stem phase", terminal=True)
try:
# Stem out blocks for (roughly) remaining epoch time
asyncio.run(stem_out(dandelion_phase))
except TimeoutError:
pass
except Exception:
logging.error(traceback.format_exc())
logger.error(traceback.format_exc(), terminal=True)
pass
else:
#logging.debug("Entering fluff phase")
#logger.debug("Entering fluff phase", terminal=True)
# Add block to primary block db, where the diffuser can read it
sleep(0.1)
store_blocks(dandelion_phase)
@ -101,7 +101,7 @@ def start_gossip_client():
# transport plugin handles the new peer
add_onionr_thread(
get_new_peers,
120, 'get_new_peers', initial_sleep=120)
60, 'get_new_peers', initial_sleep=120)
# Start a new thread to stream blocks from peers
# These blocks are being diffused and are stored in

View File

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .. import Peer
from logger import log as logging
import logger
import onionrplugins
from ..commands import GossipCommands, command_to_byte
@ -28,7 +28,7 @@ def do_announce():
sock.sendall(command_to_byte(GossipCommands.ANNOUNCE))
sock.sendall(our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1:
logging.warn(
logger.warn(
f"Could not announce with {announce_peer.transport_address}")
sock.close()

View File

@ -11,7 +11,7 @@ from ordered_set import OrderedSet
import config
from onionrthreads import add_delayed_thread
from blockdb import add_block_to_db
from logger import log as logging
import logger
from ...constants import BLACKHOLE_EVADE_TIMER_SECS, OUTBOUND_DANDELION_EDGES
from ...commands import GossipCommands, command_to_byte
@ -45,9 +45,9 @@ async def _setup_edge(
try:
s = peer.get_socket(12)
except TimeoutError:
logging.debug(f"{peer.transport_address} timed out when trying stemout")
logger.debug(f"{peer.transport_address} timed out when trying stemout")
except Exception:
logging.debug(traceback.format_exc())
logger.debug(traceback.format_exc())
return
try:
@ -56,18 +56,18 @@ async def _setup_edge(
if s.recv(1) == dandelion.StemAcceptResult.DENY:
raise StemConnectionDenied
except TimeoutError:
logging.debug(
"Peer timed out when establishing stem connection")
logging.debug(traceback.format_exc())
logger.debug(
"Peer timed out when establishing stem connection", terminal=True)
logger.debug(traceback.format_exc())
except StemConnectionDenied:
logging.debug(
logger.debug(
"Stem connection denied (peer has too many) " +
f"{peer.transport_address}")
logging.debug(traceback.format_exc())
logger.debug(traceback.format_exc())
except Exception:
logging.warn(
logger.warn(
"Error asking peer to establish stem connection" +
traceback.format_exc())
traceback.format_exc(), terminal=True)
else:
# Return peer socket if it is in stem reception mode successfully
return s
@ -113,10 +113,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
await _setup_edge(gossip_peer_set, tried_edges))
except NotEnoughEdges:
# No possible edges at this point (edges < OUTBOUND_DANDELION_EDGE)
#logging.debug(
#logger.debug(
# "Making too few edges for stemout " +
# "this is bad for anonymity if frequent.",
# )
# terminal=True)
if strict_dandelion:
not_enough_edges = True
else:
@ -133,10 +133,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
else:
# Ran out of time for stem phase
if not d_phase.is_stem_phase() or d_phase.remaining_time() < 5:
logging.error(
logger.error(
"Did not stem out any blocks in time, " +
"if this happens regularly you may be under attack",
)
terminal=False)
for s in peer_sockets:
if s:
s.close()
@ -155,7 +155,7 @@ async def stem_out(d_phase: 'DandelionPhase'):
except Empty:
pass
except Exception:
logging.warn(traceback.format_exc())
logger.warn(traceback.format_exc())
else:
# stream routine exited early
pass

View File

@ -4,7 +4,7 @@ from queue import Empty
from typing import TYPE_CHECKING
from logger import log as logging
import logger
from ...constants import BLOCK_ID_SIZE, BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
if TYPE_CHECKING:
@ -22,7 +22,7 @@ async def do_stem_stream(
remaining_time = d_phase.remaining_time()
my_phase_id = d_phase.phase_id
while remaining_time > 1 and my_phase_id == d_phase.phase_id:
# Primary client component that communicate's with gossip.server.acceptstem
remaining_time = d_phase.remaining_time()
@ -35,7 +35,7 @@ async def do_stem_stream(
await sleep(1)
else:
break
logging.info("Sending block over dandelion++")
logger.info("Sending block over dandelion++", terminal=True)
block_size = str(len(bl.raw)).zfill(BLOCK_SIZE_LEN)
def _send_it():

View File

@ -6,7 +6,9 @@ if TYPE_CHECKING:
from socket import socket
from onionrplugins import onionrevents
from logger import log as logging
import logger
from socks import GeneralProxyError
from ..peer import Peer
from ..commands import GossipCommands, command_to_byte
@ -21,9 +23,12 @@ def _do_ask_peer(peer):
try:
_ask_peer(peer)
except TimeoutError:
logging.debug("Timed out when asking for new peers")
logger.debug("Timed out when asking for new peers")
except GeneralProxyError:
logger.debug("Proxy error")
logger.debug(format_exc(), terminal=True)
except Exception:
logging.error(format_exc())
logger.error(format_exc(), terminal=True)
def _ask_peer(peer):
s: 'socket' = peer.get_socket(12)
@ -44,14 +49,14 @@ def _ask_peer(peer):
'address': peer,
'callback': connectpeer.connect_peer
}
#logging.info("Got new peer from exchange " + peer.decode('utf-8'))
logger.info("Got new peer from exchange " + peer.decode('utf-8'), terminal=True)
onionrevents.event('announce_rec', data=connect_data, threaded=True)
s.close()
def get_new_peers():
if not len(gossip_peer_set):
logging.debug("Peer set empty, cannot get new peers")
logger.debug("Peer set empty, cannot get new peers")
return
# Deep copy the peer list
@ -74,7 +79,7 @@ def get_new_peers():
threads = []
for peer in peers_we_ask:
t = Thread(
target=_do_ask_peer,
target=_do_ask_peer,
args=[peer], daemon=True, name='_do_ask_peer')
t.start()
threads.append(t)

View File

@ -3,7 +3,6 @@ from threading import Thread
from queue import Queue
from queue import Empty
from onionrplugins.onionrevents import event
import blockdb
if TYPE_CHECKING:
@ -33,9 +32,9 @@ def store_blocks(dandelion_phase: 'DandelionPhase'):
while not dandelion_phase.is_stem_phase() \
and dandelion_phase.remaining_time() > 1:
try:
bl = new_queue.get(timeout=dandelion_phase.remaining_time() + 1)
blockdb.add_block_to_db(bl)
event('gotblock', data=bl, threaded=True)
event(f'gotblock{bl.type}', data=bl, threaded=True)
blockdb.add_block_to_db(
new_queue.get(timeout=dandelion_phase.remaining_time() + 1)
)
except Empty:
pass

View File

@ -22,7 +22,7 @@ if TYPE_CHECKING:
from ordered_set import OrderedSet
from logger import log as logging
import logger
import onionrblocks
from ...peerset import gossip_peer_set
@ -67,11 +67,11 @@ def stream_from_peers():
stream_times = 100
try:
sock = peer.get_socket(CONNECT_TIMEOUT)
except (TimeoutError, ConnectionRefusedError) as _:
except ConnectionRefusedError:
need_socket_lock.release()
return
except Exception:
logging.warn(traceback.format_exc())
logger.warn(traceback.format_exc(), terminal=True)
need_socket_lock.release()
return
try:
@ -83,7 +83,7 @@ def stream_from_peers():
while stream_times >= stream_counter:
stream_counter += 1
#logging.debug("Reading block of id in stream with " + peer.transport_address)
logger.debug("Reading block of id in stream with " + peer.transport_address, terminal=True)
sock.settimeout(5)
block_id = sock.recv(BLOCK_ID_SIZE)
if blockdb.has_block(block_id):
@ -91,22 +91,22 @@ def stream_from_peers():
continue
sock.sendall(int(1).to_bytes(1, 'big'))
#logging.debug("Reading block size in stream")
#logger.debug("Reading block size in stream", terminal=True)
sock.settimeout(5)
block_size = int(sock.recv(BLOCK_SIZE_LEN))
if block_size > BLOCK_MAX_SIZE or block_size <= 0:
logging.warn(
logger.warn(
f"Peer {peer.transport_address} " +
"reported block size out of range")
break
sock.settimeout(5)
block_data = sock.recv(block_size)
#logging.debug(
#logger.debug(
# "We got a block from stream, assuming it is valid",
# )
# terminal=True)
try:
blockdb.add_block_to_db(
onionrblocks.Block(
@ -118,20 +118,19 @@ def stream_from_peers():
raise
# Tell them to keep streaming
sock.sendall(int(1).to_bytes(1, 'big'))
except (BrokenPipeError, TimeoutError, ConnectionError) as e:
except (BrokenPipeError, TimeoutError) as e:
pass
#logging.debug(f"{e} when streaming from peers")
#logging.debug(traceback.format_exc())
#logger.debug(f"{e} when streaming from peers", terminal=True)
#logger.debug(traceback.format_exc())
except Exception:
logging.warn(traceback.format_exc())
logger.warn(traceback.format_exc(), terminal=True)
finally:
sock.close()
need_socket_lock.release()
# spawn stream threads infinitely
while True:
if not gossip_peer_set:
sleep(2)
available_set = gossip_peer_set - tried_peers
if not len(available_set) and len(tried_peers):
try:
@ -158,4 +157,4 @@ def stream_from_peers():
except IndexError:
need_socket_lock.release()
break

View File

@ -2,7 +2,7 @@ import traceback
from gossip.commands import GossipCommands, command_to_byte
from .peerset import gossip_peer_set
from logger import log as logging
import logger
def connect_peer(peer):
@ -11,12 +11,12 @@ def connect_peer(peer):
try:
s = peer.get_socket(120)
except Exception:
logging.warn(f"Could not connect to {peer.transport_address}")
logging.warn(traceback.format_exc())
logger.warn(f"Could not connect to {peer.transport_address}")
logger.warn(traceback.format_exc())
else:
with s:
s.sendall(command_to_byte(GossipCommands.PING))
if s.recv(4).decode('utf-8') == 'PONG':
gossip_peer_set.add(peer)
logging.info(f"connected to {peer.transport_address}")
logger.info(f"connected to {peer.transport_address}", terminal=True)

View File

@ -12,7 +12,7 @@ from gossip import constants
from ..connectpeer import connect_peer
from onionrplugins import onionrevents
from logger import log as logging
import logger
if TYPE_CHECKING:
from onionrblocks import Block
@ -88,9 +88,9 @@ def gossip_server():
try:
await diffuse_blocks(reader, writer)
except Exception:
logging.warn(
logger.warn(
f"Err streaming blocks\n{traceback.format_exc()}",
)
terminal=True)
case GossipCommands.PUT_BLOCKS:
# Pick block queue & append stemmed blocks to it
try:
@ -99,18 +99,18 @@ def gossip_server():
inbound_dandelion_edge_count)
except asyncio.exceptions.TimeoutError:
pass
logging.debug(
logger.debug(
"Inbound edge timed out when steming blocks to us",
)
terminal=True)
except asyncio.exceptions.IncompleteReadError:
pass
logging.debug(
logger.debug(
"Inbound edge timed out (Incomplete Read) when steming blocks to us",
)
terminal=True)
except Exception:
logging.warn(
logger.warn(
f"Err accepting stem blocks\n{traceback.format_exc()}",
)
terminal=True)
# Subtract dandelion edge, make sure >=0
inbound_dandelion_edge_count[0] = \
max(inbound_dandelion_edge_count[0] - 1, 0)
@ -120,13 +120,14 @@ def gossip_server():
if blockdb.has_block(block_id):
writer.write(int(0).to_bytes(1, 'big'))
else:
writer.write(int(1).to_bytes(1, 'big'))
await writer.drain()
block_size = int(await asyncio.wait_for(reader.readexactly(constants.BLOCK_SIZE_LEN), 30))
block_data = await reader.readexactly(block_size)
Thread(
target=add_block_to_db,
target=add_block_to_db,
args=[
Block(block_id, block_data, auto_verify=True)]
).start()
@ -136,7 +137,6 @@ def gossip_server():
await writer.drain()
except BrokenPipeError:
pass
writer.close()
async def main():

View File

@ -1,4 +1,3 @@
import traceback
from typing import TYPE_CHECKING
from typing import List
import secrets
@ -6,7 +5,7 @@ from asyncio import wait_for
from onionrblocks import Block
from logger import log as logging
import logger
from ..dandelion import StemAcceptResult
from ..constants import BLOCK_ID_SIZE, BLOCK_SIZE_LEN, BLOCK_MAX_SIZE
from ..constants import MAX_INBOUND_DANDELION_EDGE, MAX_STEM_BLOCKS_PER_STREAM
@ -36,13 +35,13 @@ async def accept_stem_blocks(
for _ in range(MAX_STEM_BLOCKS_PER_STREAM):
read_routine = reader.readexactly(BLOCK_ID_SIZE)
#logging.debug(f"Reading block id in stem server")
logger.debug(f"Reading block id in stem server", terminal=True)
block_id = await wait_for(read_routine, base_wait_timeout)
block_id = block_id.decode('utf-8')
if not block_id:
break
#logging.debug(f"Reading block size in stem server")
logger.debug(f"Reading block size in stem server", terminal=True)
block_size = (await wait_for(
reader.readexactly(BLOCK_SIZE_LEN),
base_wait_timeout)).decode('utf-8')
@ -55,25 +54,17 @@ async def accept_stem_blocks(
if block_size > BLOCK_MAX_SIZE:
raise ValueError("Max block size")
#logging.debug(f"Reading block of size {block_size} in stem server")
logger.debug(f"Reading block of size {block_size} in stem server", terminal=True)
raw_block: bytes = await wait_for(
reader.readexactly(block_size), base_wait_timeout * 6)
if not raw_block:
break
try:
bl = Block(block_id, raw_block, auto_verify=True)
except Exception as e:
logging.warn(
f"Error in received stem block {block_id} {str(e)}")
logging.debug(traceback.format_exc())
break
logging.debug("Got a stem block, put into queue")
block_queue_to_use.put(bl)
logger.debug("Got a stem block, put into queue", terminal=True)
block_queue_to_use.put(
Block(block_id, raw_block, auto_verify=True)
)
# Regardless of stem phase, we add to queue
# Client will decide if they are to be stemmed

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
from ..constants import BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
from ..constants import BLOCK_STREAM_OFFSET_DIGITS
from logger import log as logging
import logger
import blockdb
from blockdb import get_blocks_after_timestamp, block_storage_observers
"""
@ -103,5 +103,5 @@ async def diffuse_blocks(reader: 'StreamReader', writer: 'StreamWriter'):
except ConnectionResetError:
pass
except Exception:
logging.warn(traceback.format_exc())
logger.warn(traceback.format_exc(), terminal=True)

81
src/keymanager.py Executable file
View File

@ -0,0 +1,81 @@
"""Onionr - Private P2P Communication.
Load, save, and delete the user's public key pairs (does not handle peer keys)
"""
from onionrutils import bytesconverter
from onionrcrypto import generate
import filepaths
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
class KeyManager:
def __init__(self):
self.keyFile = filepaths.keys_file
def addKey(self, pubKey=None, privKey=None):
"""Add a new key pair.
either specified or None to generate a new pair automatically
"""
if type(pubKey) is type(None) and type(privKey) is type(None):
pubKey, privKey = generate.generate_pub_key()
pubKey = bytesconverter.bytes_to_str(pubKey)
privKey = bytesconverter.bytes_to_str(privKey)
try:
if pubKey in self.getPubkeyList():
raise ValueError('Pubkey already in list: %s' % (pubKey,))
except FileNotFoundError:
pass
with open(self.keyFile, "a") as keyFile:
keyFile.write(pubKey + ',' + privKey + '\n')
return (pubKey, privKey)
def removeKey(self, pubKey):
"""Remove a key pair by pubkey"""
keyList = self.getPubkeyList()
keyData = ''
try:
keyList.remove(pubKey)
except ValueError:
return False
else:
keyData = ','.join(keyList)
with open(self.keyFile, "w") as keyFile:
keyFile.write(keyData)
def getPubkeyList(self):
"""Return a list of the user's keys"""
keyList = []
try:
with open(self.keyFile, "r") as keyFile:
keyData = keyFile.read()
except FileNotFoundError:
keyData = ''
keyData = keyData.split('\n')
for pair in keyData:
if len(pair) > 0:
keyList.append(pair.split(',')[0])
return keyList
def getPrivkey(self, pubKey):
privKey = None
with open(self.keyFile, "r") as keyFile:
keyData = keyFile.read()
for pair in keyData.split('\n'):
if pubKey in pair or pubKey.replace('=', '') in pair:
privKey = pair.split(',')[1]
return privKey

View File

@ -1,92 +1,71 @@
"""
Onionr - Private P2P Communication
'''
Onionr - Private P2P Communication
We use built in logging but with a custom formatter for colors and such
"""
import logging
import sys
This file handles all operations involving logging
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
from filepaths import log_file
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import sys, traceback
# credit: https://stackoverflow.com/a/384076
# license: https://creativecommons.org/licenses/by-sa/4.0/
class ConsoleFormatter(logging.Formatter):
from . import colors, readline, log, raw, confirm, colors, settings
colors = colors.Colors
readline = readline.readline
log = log.log
raw = raw.raw
confirm = confirm.confirm
grey = "\x1b[38;20m"
green = "\x1b[38;5;82m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
# debug: when there is info that could be useful for debugging purposes only
def debug(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_DEBUG):
if settings.get_level() <= level:
log('/', data, timestamp = timestamp, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
FORMATS = {
logging.DEBUG: grey + format_default + reset,
logging.INFO: green + format_info + reset,
logging.WARNING: yellow + format_default + reset,
logging.ERROR: red + format_default + reset,
logging.CRITICAL: bold_red + format_default + reset
}
# info: when there is something to notify the user of, such as the success of a process
def info(data: str, timestamp = False, prompt = True, terminal = False, level = settings.LEVEL_INFO):
if settings.get_level() <= level:
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, terminal = terminal)
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# warn: when there is a potential for something bad to happen
def warn(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_WARN):
if not error is None:
debug('Error: ' + str(error) + parse_error())
if settings.get_level() <= level:
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, terminal = terminal)
class FileFormatter(logging.Formatter):
# error: when only one function, module, or process of the program encountered a problem and must stop
def error(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_ERROR):
if settings.get_level() <= level:
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
# fatal: when the something so bad has happened that the program must stop
def fatal(data: str, error = None, timestamp=True, prompt = True, terminal = False, level = settings.LEVEL_FATAL):
if not error is None:
debug('Error: ' + str(error) + parse_error(), terminal = terminal)
if settings.get_level() <= level:
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
# returns a formatted error message
def parse_error():
details = traceback.extract_tb(sys.exc_info()[2])
output = ''
FORMATS = {
logging.DEBUG: format_default,
logging.INFO: format_info,
logging.WARNING: format_default,
logging.ERROR: format_default,
logging.CRITICAL: format_default
}
for line in details:
output += '\n ... module %s in %s:%i' % (line[2], line[0], line[1])
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
#logging.basicConfig(level=logging.ERROR, format='%(message)s ')
log = logging.getLogger('onionr')
log.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO)
ch.setFormatter(ConsoleFormatter())
def enable_file_logging():
fh = logging.FileHandler(log_file)
fh.setLevel(logging.INFO)
fh.setFormatter(FileFormatter())
log.addHandler(fh)
def disable_console_logging():
log.removeHandler(ch)
def enable_console_logging():
log.addHandler(ch)
enable_console_logging()
return output

60
src/logger/colors.py Normal file
View File

@ -0,0 +1,60 @@
'''
Onionr - Private P2P Communication
class to access ANSI control codes
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import re
class Colors:
'''
This class allows you to set the color if ANSI codes are supported
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'
italics='\033[3m'
class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'
class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
@staticmethod
def filter(data):
return re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]').sub('', str(data))

54
src/logger/confirm.py Normal file
View File

@ -0,0 +1,54 @@
'''
Onionr - Private P2P Communication
confirm y/n cli prompt
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def confirm(default = 'y', message = 'Are you sure %s? '):
'''
Displays an "Are you sure" message, returns True for Y and False for N
message: The confirmation message, use %s for (y/n)
default: which to prefer-- y or n
'''
color = colors.fg.green + colors.bold
default = default.lower()
confirm = colors.bold
if default.startswith('y'):
confirm += '(Y/n)'
else:
confirm += '(y/N)'
confirm += colors.reset + color
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output.replace('%s', confirm))
inp = input().lower()
if 'y' in inp:
return True
if 'n' in inp:
return False
else:
return default == 'y'

38
src/logger/log.py Normal file
View File

@ -0,0 +1,38 @@
'''
Onionr - Private P2P Communication
god log function
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys, time
from . import colors, raw, settings
colors = colors.Colors
def log(prefix, data, color = '', timestamp=True, fd = sys.stdout, prompt = True, terminal = False):
'''
Logs the data
prefix : The prefix to the output
data : The actual data to output
color : The color to output before the data
'''
curTime = ''
if timestamp:
curTime = time.strftime("%m-%d %H:%M:%S") + ' '
output = colors.reset + str(color) + ('[' + colors.bold + str(prefix) + colors.reset + str(color) + '] ' if prompt is True else '') + curTime + str(data) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
raw.raw(output, fd = fd, terminal = terminal)

54
src/logger/raw.py Normal file
View File

@ -0,0 +1,54 @@
"""Onionr - Private P2P Communication.
Output raw data to file or terminal
"""
import sys
import os
from . import settings, colors
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
colors = colors.Colors
def raw(data, fd = sys.stdout, terminal = False):
"""
Outputs raw data to console without formatting
"""
if terminal and (settings.get_settings() & settings.OUTPUT_TO_CONSOLE):
try:
ts = fd.write('%s\n' % data)
except OSError:
pass
if settings.get_settings() & settings.OUTPUT_TO_FILE:
fdata = ''
try:
for _ in range(5):
try:
with open(settings._outputfile, 'r') as file:
fdata = file.read()
except UnicodeDecodeError:
pass
else:
break
except FileNotFoundError:
pass
fdata = fdata + '\n' + data
fdata = fdata.split('\n')
if len(fdata) >= settings.MAX_LOG_FILE_LINES:
fdata.pop(0)
fdata = '\n'.join(fdata)
with open(settings._outputfile, 'w') as file:
file.write(fdata)

37
src/logger/readline.py Normal file
View File

@ -0,0 +1,37 @@
'''
Onionr - Private P2P Communication
get a line of input from stdin
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def readline(message = ''):
'''
Takes in input from the console, not stored in logs
message: The message to display before taking input
'''
color = colors.fg.green + colors.bold
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output)
return input()

89
src/logger/settings.py Normal file
View File

@ -0,0 +1,89 @@
'''
Onionr - Private P2P Communication
logger settings
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import os
from utils import identifyhome
import filepaths
data_home = os.environ.get('ONIONR_LOG_DIR', identifyhome.identify_home())
# Use the bitwise operators to merge these settings
USE_ANSI = 0b100
if os.name == 'nt':
USE_ANSI = 0b000
OUTPUT_TO_CONSOLE = 0b010
OUTPUT_TO_FILE = 0b001
LEVEL_DEBUG = 1
LEVEL_INFO = 2
LEVEL_WARN = 3
LEVEL_ERROR = 4
LEVEL_FATAL = 5
LEVEL_IMPORTANT = 6
MAX_LOG_FILE_LINES = 10000
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
_level = LEVEL_DEBUG # the lowest level to log
# the file to log to
_outputfile = filepaths.log_file
def set_settings(type):
'''
Set the settings for the logger using bitwise operators
'''
global _type
_type = type
def get_settings():
'''
Get settings from the logger
'''
return _type
def set_level(level):
'''
Set the lowest log level to output
'''
global _level
_level = level
def get_level()->int:
'''
Get the lowest log level currently being outputted
'''
return _level
def set_file(outputfile):
'''
Set the file to output to, if enabled
'''
global _outputfile
_outputfile = outputfile
def get_file():
'''
Get the file to output to
'''
return _outputfile

View File

@ -8,19 +8,20 @@ import sys
import platform
import signal
from threading import Thread
from logger import log as logging
from logger import enable_file_logging
import filenuke
import psutil
import config
import logger
from onionrplugins import onionrevents as events
from utils import identifyhome
import filepaths
import onionrvalues
from onionrutils import cleanup
from onionrcrypto import getourkeypair
from onionrthreads import add_onionr_thread
from blockdb.blockcleaner import clean_block_database
from .. import version
@ -43,39 +44,25 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _safe_remove(path):
try:
os.remove(path)
except FileNotFoundError:
pass
def delete_run_files():
"""Delete run files, do not error if not found.
Test: test_cleanup.py
"""
_safe_remove(filepaths.lock_file)
_safe_remove(filepaths.gossip_server_socket_file)
_safe_remove(filepaths.pid_file)
def _show_info_messages():
version.version(verbosity=5, function=logging.info)
logging.debug('Python version %s' % platform.python_version())
version.version(verbosity=5, function=logger.info)
logger.debug('Python version %s' % platform.python_version())
if onionrvalues.DEVELOPMENT_MODE:
logging.warn('Development mode enabled')
logger.warn('Development mode enabled', timestamp=False, terminal=True)
logger.info('Using public key: %s' %
(logger.colors.underline +
getourkeypair.get_keypair()[0][:52]))
def daemon():
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
if config.get('log.file.output', False):
enable_file_logging()
def _handle_sig_term(signum, frame):
sys.exit(0)
with open(filepaths.pid_file, 'w') as f:
f.write(str(os.getpid()))
@ -87,30 +74,26 @@ def daemon():
security_level = config.get('general.security_level', 1)
_show_info_messages()
logging.info(
f"Onionr daemon is running under pid {os.getpid()}")
logger.info(
f"Onionr daemon is running under pid {os.getpid()}", terminal=True)
events.event('init', threaded=False)
events.event('afterinit', threaded=False)
events.event('daemon_start')
add_onionr_thread(
clean_block_database, 60, 'clean_block_database', initial_sleep=0)
Thread(
target=gossip.start_gossip_threads,
daemon=True,
target=gossip.start_gossip_threads,
daemon=True,
name='start_gossip_threads').start()
try:
while True:
# Mainly for things like repls
events.event('primary_loop', threaded=False)
sleep(60)
except KeyboardInterrupt:
pass
delete_run_files()
cleanup.delete_run_files()
if security_level >= 2:
filenuke.nuke.clean_tree(identifyhome.identify_home())
@ -121,25 +104,33 @@ def start(override: bool = False):
Error exit if there is and its not overridden
"""
if os.path.exists(filepaths.lock_file) and not override:
if os.path.exists(filepaths.restarting_indicator):
try:
os.remove(filepaths.restarting_indicator)
except FileNotFoundError:
pass
else:
return
with open(filepaths.lock_file, 'r') as lock_file:
try:
proc = psutil.Process(int(lock_file.read())).name()
except psutil.NoSuchProcess:
proc = ""
if not proc.startswith("python"):
logging.warn(
f"Detected stale run file, deleting {filepaths.lock_file}")
logger.warn(
f"Detected stale run file, deleting {filepaths.lock_file}",
terminal=True)
try:
os.remove(filepaths.lock_file)
except FileNotFoundError:
pass
start(override=True)
return
logging.error('Cannot start. Daemon is already running,'
logger.fatal('Cannot start. Daemon is already running,'
+ ' or it did not exit cleanly.\n'
+ ' (if you are sure that there is not a daemon running,'
+ f' delete {filepaths.lock_file} & try again).',
)
terminal=True)
else:
if not onionrvalues.DEVELOPMENT_MODE:
lock_file = open(filepaths.lock_file, 'w')

View File

@ -0,0 +1,24 @@
"""Onionr - Private P2P Communication.
Open the web interface properly into a web browser, and return it
"""
import logger
from onionrutils import getclientapiserver
def get_url(config) -> str:
"""Build UI URL string and return it."""
onboarding = ""
if not config.get('onboarding.done', False):
onboarding = "onboarding/"
try:
url = getclientapiserver.get_client_API_server()
except FileNotFoundError:
url = ""
logger.error(
'Onionr seems to not be running (could not get api host)',
terminal=True)
else:
url = 'http://%s/%s#%s' % (url, onboarding, config.get('client.webpassword'))
logger.info('Onionr web interface URL: ' + url, terminal=True)
return url

View File

@ -6,7 +6,7 @@ import os
from signal import SIGTERM
from filepaths import pid_file
from logger import log as logging
import logger
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -29,8 +29,9 @@ def kill_daemon():
with open(pid_file, 'r') as pid:
os.kill(int(pid.read()), SIGTERM)
except FileNotFoundError:
logging.error("Daemon not running/pid file missing")
logging.warn('Stopping the running daemon, if one exists...')
logger.error("Daemon not running/pid file missing")
logger.warn('Stopping the running daemon, if one exists...', timestamp=False,
terminal=True)
kill_daemon.onionr_help = "Gracefully stops the " # type: ignore

View File

@ -5,12 +5,11 @@ Show nice logo
import os
import config
import logger
from .quotes import QUOTE
from utils.boxprint import bordered
from utils import readstatic
import onionrvalues
from utils import logoheader
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,34 +25,28 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def header():
if onionrvalues.DEVELOPMENT_MODE:
return
pink_ansi = '\033[95m'
green_ansi = '\033[92m'
reset_ansi = '\x1b[0m'
logo = readstatic.read_static('header.txt', ret_bin=False)
logo = logo.replace('P', pink_ansi).replace('G', green_ansi).replace('W', reset_ansi)
print(reset_ansi + logo)
def show_logo():
logger.raw('', terminal=True)
try:
terminal_size = os.get_terminal_size().columns
except OSError: # Generally thrown if not in terminal
terminal_size = 120
# print nice header thing :)
if config.get('general.display_header', True):
header()
logoheader.header("")
if terminal_size >= 120:
if QUOTE[1]: # If there is an author to show for the quote
print("\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]))
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]),
terminal=True)
else:
print("\u001b[33m\033[F" + bordered(QUOTE[0]))
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0]), terminal=True)
else:
if QUOTE[1]:
print("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1])
logger.info("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1],
terminal=True)
else:
print("\u001b[33m\033[F" + QUOTE[0])
logger.info("\u001b[33m\033[F" + QUOTE[0], terminal=True)

View File

@ -0,0 +1,146 @@
"""Onionr - Private P2P Communication.
This module defines commands to show stats/details about the local node
"""
import os
import logger
from onionrutils import mnemonickeys
from utils import sizeutils, getconsolewidth, identifyhome
from coredb import keydb
import onionrcrypto
import config
import onionrvalues
from filepaths import lock_file
import psutil
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _is_running():
script = onionrvalues.SCRIPT_NAME
if os.path.isfile(lock_file):
for process in psutil.process_iter():
if process.name() == script:
return True
return False
def show_stats():
"""Print/log statistic info about our Onionr install."""
try:
# define stats messages here
home = identifyhome.identify_home()
messages = {
# info about local client
# This line is inaccurate if dev mode is enabled
'Onionr Daemon Status':
((logger.colors.fg.green + 'Online') \
if _is_running() \
else logger.colors.fg.red + 'Offline'),
# file and folder size stats
'div1': True, # this creates a solid line across the screen, a div
'Total Block Size':
sizeutils.human_size(sizeutils.size(home + 'blocks.db')),
'Total Plugin Size':
sizeutils.human_size(sizeutils.size(home + 'plugins/')),
'Log File Size':
sizeutils.human_size(sizeutils.size(home + 'output.log')),
# count stats
'div2': True,
'Enabled Plugins':
str(len(config.get('plugins.enabled', list()))) + ' / ' +
str(len(os.listdir(home + 'plugins/')))
}
# color configuration
colors = {
'title': logger.colors.bold,
'key': logger.colors.fg.lightgreen,
'val': logger.colors.fg.green,
'border': logger.colors.fg.lightblue,
'reset': logger.colors.reset
}
# pre-processing
maxlength = 0
width = getconsolewidth.get_console_width()
for key, val in messages.items():
if not (type(val) is bool and val is True):
maxlength = max(len(key), maxlength)
prewidth = maxlength + len(' | ')
groupsize = width - prewidth - len('[+] ')
# generate stats table
logger.info(colors['title'] + 'Onionr v%s Statistics' %
onionrvalues.ONIONR_VERSION + colors['reset'],
terminal=True)
logger.info(colors['border'] + '-' * (maxlength + 1) +
'+' + colors['reset'], terminal=True)
for key, val in messages.items():
if not (type(val) is bool and val is True):
val = [str(val)[i:i + groupsize]
for i in range(0, len(str(val)), groupsize)]
logger.info(colors['key'] + str(key).rjust(maxlength) +
colors['reset'] + colors['border'] +
' | ' + colors['reset'] + colors['val'] +
str(val.pop(0)) + colors['reset'], terminal=True)
for value in val:
logger.info(' ' * maxlength + colors['border'] + ' | ' +
colors['reset'] + colors['val'] + str(
value) + colors['reset'], terminal=True)
else:
logger.info(colors['border'] + '-' * (maxlength +
1) + '+' +
colors['reset'], terminal=True)
logger.info(colors['border'] + '-' * (maxlength + 1) +
'+' + colors['reset'], terminal=True)
except Exception as e: # pylint: disable=W0703
logger.error('Failed to generate statistics table. ' +
str(e), error=e, timestamp=False, terminal=True)
def show_details():
"""Print out details.
node transport address(es)
active user ID
active user ID in mnemonic form
"""
details = {
'Data directory': identifyhome.identify_home(),
'Public Key': onionrcrypto.pub_key.replace('=', ''),
'Human-readable Public Key': mnemonickeys.get_human_readable_ID()
}
for detail in details:
logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen,
detail, logger.colors.fg.green,
details[detail]), terminal=True)
show_details.onionr_help = "Shows relevant information " # type: ignore
show_details.onionr_help += "for your Onionr install:"
show_stats.onionr_help = "Shows statistics for your Onionr " # type: ignore
show_stats.onionr_help += "node. Slow if Onionr is not running" # type: ignore

View File

@ -11,7 +11,7 @@ try:
except (KeyError, IndexError) as _:
pass
from logger import log as logging
import logger
import onionrexceptions
import onionrplugins
from onionrplugins import onionrpluginapi
@ -48,6 +48,10 @@ def register_plugin_commands(cmd) -> bool:
return False
def _show_term(msg: str):
logger.info(msg, terminal=True)
def register():
"""Register commands and handles help command processing."""
def get_help_message(cmd: str,
@ -76,7 +80,7 @@ def register():
try:
cmd = sys.argv[1]
except IndexError:
logging.info('Run with --help to see available commands')
logger.info('Run with --help to see available commands', terminal=True)
sys.exit(10)
is_help_cmd = False
@ -98,28 +102,29 @@ def register():
sys.argv[2]
except IndexError:
for i in arguments.get_arguments():
logging.info('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
_show_term('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
get_help_message(i[0])))
for pl in onionrplugins.get_enabled_plugins():
pl = onionrplugins.get_plugin(pl)
if hasattr(pl, 'ONIONR_COMMANDS'):
print('')
try:
logging.info('%s commands:' % (pl.plugin_name,))
_show_term('%s commands:' % (pl.plugin_name,))
except AttributeError:
logging.info('%s commands:' % (pl.__name__,))
_show_term('%s commands:' % (pl.__name__,))
for plugin_cmd in pl.ONIONR_COMMANDS:
logging.info('%s %s: %s' %
_show_term('%s %s: %s' %
(PROGRAM_NAME,
plugin_cmd,
get_help_message(plugin_cmd)),)
print('')
else:
try:
logging.info('%s %s: %s' % (PROGRAM_NAME,
_show_term('%s %s: %s' % (PROGRAM_NAME,
sys.argv[2],
get_help_message(sys.argv[2])))
except KeyError:
logging.error('%s: command does not exist.' % [sys.argv[2]])
logger.error('%s: command does not exist.' % [sys.argv[2]],
terminal=True)
sys.exit(3)
return

View File

@ -4,7 +4,8 @@ Sets CLI arguments for Onionr
"""
from typing import Callable
from .. import version, daemonlaunch
from .. import onionrstatistics, version, daemonlaunch
from .. import pubkeymanager # commands to add or change id
from .. import resetplugins # command to reinstall default plugins
@ -32,10 +33,14 @@ def get_arguments() -> dict:
dynamically modify them with plugins
"""
args = {
('details', 'info'): onionrstatistics.show_details,
('stats', 'statistics'): onionrstatistics.show_stats,
('version',): version.version,
('start', 'daemon'): daemonlaunch.start,
('stop', 'kill'): daemonlaunch.kill_daemon,
('resetplugins', 'reset-plugins', 'updateplugins', 'update-plugins'): resetplugins.reset
('addid', 'add-id'): pubkeymanager.add_ID,
('changeid', 'change-id'): pubkeymanager.change_ID,
('resetplugins', 'reset-plugins'): resetplugins.reset
}
return args

View File

@ -4,7 +4,7 @@ Try to provide recommendations for invalid Onionr commands
"""
import sys
from difflib import SequenceMatcher
from logger import log as logging
import logger
from . import arguments
"""
This program is free software: you can redistribute it and/or modify
@ -30,9 +30,9 @@ def recommend(print_default: bool = True):
for key in args.keys():
for word in key:
if SequenceMatcher(None, tried, word).ratio() >= 0.75:
logging.warn(f'{print_message} "{tried}", '
logger.warn(f'{print_message} "{tried}", '
+ f'did you mean "{word}"?',
)
terminal=True)
return
if print_default:
logging.error('%s "%s"' % (print_message, tried))
logger.error('%s "%s"' % (print_message, tried), terminal=True)

View File

@ -0,0 +1,95 @@
"""Onionr - Private P2P Communication.
This module defines user ID-related CLI commands
"""
import sys
import getpass
import unpaddedbase32
import niceware
import logger
import onionrexceptions
from onionrutils import stringvalidators, bytesconverter
import config
import keymanager
import onionrcrypto
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
def add_ID():
"""Command to create a new user ID key pair."""
key_manager = keymanager.KeyManager()
pw = ""
try:
sys.argv[2] # pylint: disable=W0104
if not sys.argv[2].lower() == 'true':
raise ValueError
except (IndexError, ValueError):
newID = key_manager.addKey()[0]
else:
pw = "-".join(niceware.generate_passphrase(32))
newID, privKey = onionrcrypto.generate_deterministic(pw)
try:
key_manager.addKey(pubKey=newID,
privKey=privKey)
except ValueError:
logger.error(
'That ID is already available, you can change to it ' +
'with the change-id command.', terminal=True)
return
if pw:
print("Phrase to restore ID:", pw)
logger.info('Added ID: %s' %
(bytesconverter.bytes_to_str(newID.replace('=', '')),), terminal=True)
add_ID.onionr_help = "If the first argument is true, " # type: ignore
add_ID.onionr_help += "Onionr will show a deterministic " # type: ignore
add_ID.onionr_help += "generation prompt. Otherwise it will " # type: ignore
add_ID.onionr_help += "generate & save a new random key pair." # type: ignore
def change_ID():
"""Command to change active ID from argv or stdin."""
key_manager = keymanager.KeyManager()
try:
key = sys.argv[2]
key = unpaddedbase32.repad(key.encode()).decode()
except IndexError:
logger.warn('Specify pubkey to use', terminal=True)
else:
if stringvalidators.validate_pub_key(key):
key_list = key_manager.getPubkeyList()
if key in key_list or key.replace('=', '') in key_list:
config.set('general.public_key', key)
config.save()
logger.info('Set active key to: %s' % (key,), terminal=True)
logger.info('Restart Onionr if it is running.', terminal=True)
else:
logger.warn('That key does not exist', terminal=True)
else:
logger.warn('Invalid key %s' % (key,), terminal=True)
change_ID.onionr_help = "<pubkey>: Switches Onionr to " # type: ignore
change_ID.onionr_help += "use a different user ID key. " # type: ignore
change_ID.onionr_help += "You should immediately restart " # type: ignore
change_ID.onionr_help += "Onionr if it is running." # type: ignore

View File

@ -6,7 +6,7 @@ import os
import shutil
from utils import identifyhome
from logger import log as logging
import logger
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,7 +32,7 @@ def reset():
if os.path.exists(plugin_dir):
shutil.rmtree(plugin_dir)
logging.info('Default plugins have been reset.')
logger.info('Default plugins have been reset.', terminal=True)
reset.onionr_help = "reinstalls default Onionr plugins" # type: ignore

View File

@ -5,7 +5,7 @@ Command to show version info
import platform
from utils import identifyhome
import onionrvalues
from logger import log as logging
import logger
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,21 +22,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def version(verbosity=5, function=logging.info):
def version(verbosity=5, function=logger.info):
"""Display the Onionr version."""
function('Onionr v%s (%s)' % (onionrvalues.ONIONR_VERSION,
platform.machine()))
function('Onionr v%s (%s) (API v%s)' % (onionrvalues.ONIONR_VERSION,
platform.machine(),
onionrvalues.API_VERSION),
terminal=True)
if verbosity >= 1:
function(onionrvalues.ONIONR_TAGLINE)
function(onionrvalues.ONIONR_TAGLINE, terminal=True)
if verbosity >= 2:
pf = platform.platform()
release = platform.release()
python_imp = platform.python_implementation()
python_version = platform.python_version()
function(
f'{python_imp} {python_version} on {pf} {release}')
f'{python_imp} {python_version} on {pf} {release}',
terminal=True)
function('Onionr data dir: %s' %
identifyhome.identify_home())
identifyhome.identify_home(), terminal=True)
version.onionr_help = 'Shows environment details including ' # type: ignore

27
src/onionrcrypto/__init__.py Executable file
View File

@ -0,0 +1,27 @@
'''
Onionr - Private P2P Communication
This file handles Onionr's cryptography.
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
from . import generate, hashers, getourkeypair, signing, encryption, cryptoutils
generate_deterministic = generate.generate_deterministic
generate = generate.generate_pub_key
keypair = getourkeypair.get_keypair()
pub_key = keypair[0]
priv_key = keypair[1]

View File

@ -0,0 +1,6 @@
from . import safecompare, replayvalidation
from . import getpubfrompriv
replay_validator = replayvalidation.replay_timestamp_validation
safe_compare = safecompare.safe_compare
get_pub_key_from_priv = getpubfrompriv.get_pub_key_from_priv

View File

@ -0,0 +1,28 @@
"""Onionr - Private P2P Communication.
generate a public ed25519 key from a private one
"""
from nacl import signing, encoding
from onionrtypes import UserID, UserIDSecretKey
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def get_pub_key_from_priv(priv_key: UserIDSecretKey,
raw_encoding: bool = False) -> UserID:
return signing.SigningKey(
priv_key, encoder=encoding.Base32Encoder).verify_key.encode(
encoding.Base32Encoder)

View File

@ -0,0 +1,3 @@
from onionrutils import epoch
def replay_timestamp_validation(timestamp):
return epoch.get_epoch() - int(timestamp) <= 2419200

View File

@ -0,0 +1,12 @@
import hmac
def safe_compare(one, two):
# Do encode here to avoid spawning core
try:
one = one.encode()
except AttributeError:
pass
try:
two = two.encode()
except AttributeError:
pass
return hmac.compare_digest(one, two)

View File

@ -0,0 +1,38 @@
from .. import hashers
import config, onionrproofs, logger
import onionrexceptions
def verify_POW(blockContent):
'''
Verifies the proof of work associated with a block
'''
retData = False
dataLen = len(blockContent)
try:
blockContent = blockContent.encode()
except AttributeError:
pass
blockHash = hashers.sha3_hash(blockContent)
try:
blockHash = blockHash.decode() # bytes on some versions for some reason
except AttributeError:
pass
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent)
if difficulty < int(config.get('general.minimum_block_pow')):
difficulty = int(config.get('general.minimum_block_pow'))
mainHash = '0000000000000000000000000000000000000000000000000000000000000000'#nacl.hash.blake2b(nacl.utils.random()).decode()
puzzle = mainHash[:difficulty]
if blockHash[:difficulty] == puzzle:
# logger.debug('Validated block pow')
retData = True
else:
logger.debug(f"Invalid token, bad proof for {blockHash} {puzzle}")
raise onionrexceptions.InvalidProof('Proof for %s needs to be %s' % (blockHash, puzzle))
return retData

View File

@ -0,0 +1,47 @@
import nacl.encoding, nacl.public, nacl.signing
from .. import getourkeypair
import unpaddedbase32
from onionrutils import bytesconverter, stringvalidators
pair = getourkeypair.get_keypair()
our_pub_key = unpaddedbase32.repad(pair[0].encode())
our_priv_key = unpaddedbase32.repad(pair[1].encode())
def pub_key_encrypt(data, pubkey, encodedData=False):
'''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)'''
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
retVal = ''
box = None
data = bytesconverter.str_to_bytes(data)
pubkey = nacl.signing.VerifyKey(pubkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_public_key()
if encodedData:
encoding = nacl.encoding.Base64Encoder
else:
encoding = nacl.encoding.RawEncoder
box = nacl.public.SealedBox(pubkey)
retVal = box.encrypt(data, encoder=encoding)
return retVal
def pub_key_decrypt(data, pubkey='', privkey='', encodedData=False):
'''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)'''
if pubkey != '':
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
decrypted = False
if encodedData:
encoding = nacl.encoding.Base64Encoder
else:
encoding = nacl.encoding.RawEncoder
if privkey == '':
privkey = our_priv_key
ownKey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
if stringvalidators.validate_pub_key(privkey):
privkey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
anonBox = nacl.public.SealedBox(privkey)
else:
anonBox = nacl.public.SealedBox(ownKey)
decrypted = anonBox.decrypt(data, encoder=encoding)
return decrypted

View File

@ -0,0 +1,65 @@
"""Onionr - Private P2P Communication.
functions to generate ed25519 key pairs
"""
import nacl.signing
import nacl.encoding
import nacl.pwhash
import onionrexceptions
from onionrutils import bytesconverter
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def generate_pub_key():
"""Generate a Ed25519 public key pair.
return tuple of base32encoded pubkey, privkey
"""
private_key = nacl.signing.SigningKey.generate()
public_key = private_key.verify_key.encode(
encoder=nacl.encoding.Base32Encoder())
return (public_key.decode(), private_key.encode(
encoder=nacl.encoding.Base32Encoder()).decode())
def generate_deterministic(passphrase, bypassCheck=False):
"""Generate a Ed25519 public key pair from a phase.
not intended for human-generated key
"""
passStrength = onionrvalues.PASSWORD_LENGTH
# Convert to bytes if not already
passphrase = bytesconverter.str_to_bytes(passphrase)
# Validate passphrase length
if not bypassCheck:
if len(passphrase) < passStrength:
raise onionrexceptions.PasswordStrengthError(
"Passphase must be at least %s characters" % (passStrength,))
# KDF values
kdf = nacl.pwhash.argon2id.kdf
# Does not need to be secret, but must be 16 bytes
salt = b"U81Q7llrQcdTP0Ux"
ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE
# Generate seed for ed25519 key
key = kdf(32, passphrase, salt, opslimit=ops, memlimit=mem)
key = nacl.signing.SigningKey(key)
return (
key.verify_key.encode(nacl.encoding.Base32Encoder).decode(),
key.encode(nacl.encoding.Base32Encoder).decode())

View File

@ -0,0 +1,36 @@
"""
Onionr - Private P2P Communication
returns our current active keypair
"""
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import keymanager, config, filepaths
from . import generate
def get_keypair():
key_m = keymanager.KeyManager()
if os.path.exists(filepaths.keys_file):
if len(config.get('general.public_key', '')) > 0:
pubKey = config.get('general.public_key')
else:
pubKey = key_m.getPubkeyList()[0]
privKey = key_m.getPrivkey(pubKey)
else:
keys = generate.generate_pub_key()
pubKey = keys[0]
privKey = keys[1]
key_m.addKey(pubKey, privKey)
return (pubKey, privKey)

View File

@ -0,0 +1,21 @@
import hashlib
import nacl.hash
def sha3_hash(data):
try:
data = data.encode()
except AttributeError:
pass
hasher = hashlib.sha3_256()
hasher.update(data)
return hasher.hexdigest()
def blake2b_hash(data):
try:
data = data.encode()
except AttributeError:
pass
return nacl.hash.blake2b(data)

View File

@ -0,0 +1,45 @@
import base64, binascii
import unpaddedbase32
import nacl.encoding, nacl.signing, nacl.exceptions
from onionrutils import bytesconverter
from onionrutils import mnemonickeys
import logger
def ed_sign(data, key, encodeResult=False):
'''Ed25519 sign data'''
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
try:
data = data.encode()
except AttributeError:
pass
key = nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
retData = ''
if encodeResult:
retData = key.sign(data, encoder=nacl.encoding.Base64Encoder).signature.decode() # .encode() is not the same as nacl.encoding
else:
retData = key.sign(data).signature
return retData
def ed_verify(data, key, sig, encodedData=True):
'''Verify signed data (combined in nacl) to an ed25519 key'''
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
try:
key = nacl.signing.VerifyKey(key=key, encoder=nacl.encoding.Base32Encoder)
except nacl.exceptions.ValueError:
return False
except binascii.Error:
logger.warn('Could not load key for verification, invalid padding')
return False
retData = False
sig = base64.b64decode(sig)
try:
data = data.encode()
except AttributeError:
pass
try:
retData = key.verify(data, sig) # .encode() is not the same as nacl.encoding
except nacl.exceptions.BadSignatureError:
pass
return retData

View File

@ -17,13 +17,11 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os, re
import importlib.util
import os, re, importlib
import traceback
from . import onionrevents as events
from .pluginapis import plugin_apis
import config, logging
import config, logger
from utils import identifyhome
# set data dir
@ -44,9 +42,9 @@ def reload(stop_event = True):
enabled_plugins = get_enabled_plugins()
if stop_event is True:
logging.debug('Reloading all plugins...')
logger.debug('Reloading all plugins...')
else:
logging.debug('Loading all plugins...')
logger.debug('Loading all plugins...')
if stop_event is True:
for plugin in enabled_plugins:
@ -57,7 +55,7 @@ def reload(stop_event = True):
return True
except:
logging.error('Failed to reload plugins.')
logger.error('Failed to reload plugins.')
return False
@ -74,8 +72,8 @@ def enable(name, start_event = True):
except ImportError as e: # Was getting import error on Gitlab CI test "data"
# NOTE: If you are experiencing issues with plugins not being enabled, it might be this resulting from an error in the module
# can happen inconsistently (especially between versions)
logging.error('Failed to enable module:')
logging.error(traceback.format_exc())
logger.error('Failed to enable module:', terminal=True)
logger.error(traceback.format_exc(), terminal=True)
return False
else:
enabled_plugins.append(name)
@ -87,8 +85,8 @@ def enable(name, start_event = True):
else:
return False
else:
logging.error('Failed to enable plugin \"%s\", disabling plugin.' % name)
logging.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()))
logger.error('Failed to enable plugin \"%s\", disabling plugin.' % name, terminal=True)
logger.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()), terminal=True)
disable(name)
return False
@ -130,9 +128,9 @@ def start(name):
return plugin
except:
logging.error('Failed to start module \"%s\".' % name)
logger.error('Failed to start module \"%s\".' % name)
else:
logging.error('Failed to start nonexistant module \"%s\".' % name)
logger.error('Failed to start nonexistant module \"%s\".' % name)
return None
@ -154,9 +152,9 @@ def stop(name):
return plugin
except:
logging.error('Failed to stop module \"%s\".' % name)
logger.error('Failed to stop module \"%s\".' % name)
else:
logging.error('Failed to stop nonexistant module \"%s\".' % name)
logger.error('Failed to stop nonexistant module \"%s\".' % name)
return None
@ -259,11 +257,11 @@ def check():
"""
if not config.is_set('plugins'):
logging.debug('Generating plugin configuration data...')
logger.debug('Generating plugin configuration data...')
config.set('plugins', {'enabled': []}, True)
if not os.path.exists(os.path.dirname(get_plugins_folder())):
logging.debug('Generating plugin data folder...')
logger.debug('Generating plugin data folder...')
try:
os.makedirs(os.path.dirname(get_plugins_folder()))
except FileExistsError:

View File

@ -7,7 +7,7 @@ from threading import Thread
import traceback
import config, logging
import config, logger
import onionrplugins as plugins
from . import onionrpluginapi as pluginapi
"""
@ -41,11 +41,11 @@ def __event_caller(event_name, data = {}):
try:
call(plugins.get_plugin(plugin), event_name, data, get_pluginapi(data))
except ModuleNotFoundError as _:
logging.warn('Disabling nonexistant plugin "%s"...' % plugin)
logger.warn('Disabling nonexistant plugin "%s"...' % plugin, terminal=True)
plugins.disable(plugin, stop_event = False)
except Exception as _:
logging.error('Event "%s" failed for plugin "%s".' % (event_name, plugin))
logging.error('\n' + traceback.format_exc())
logger.error('Event "%s" failed for plugin "%s".' % (event_name, plugin), terminal=True)
logger.error('\n' + traceback.format_exc(), terminal=True)
def event(event_name, data = {}, threaded = True):
"""Call an event on all plugins (if defined)"""

View File

@ -18,7 +18,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import onionrplugins, logging
import onionrplugins, logger
class PluginAPI:

View File

@ -1,7 +0,0 @@
#
from typing import Callable, Dict
# plugin apis are methods intended to be available to the rpc
# plugin, this is so plugins can provide apis to other plugins
# plugins add their methods during or before afterinit event
plugin_apis: Dict[str, Callable] = {}

120
src/onionrsetup/dbcreator.py Executable file
View File

@ -0,0 +1,120 @@
"""Onionr - Private P2P Communication.
DBCreator, creates sqlite3 databases used by Onionr
"""
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import sqlite3, os
from coredb import dbfiles
import filepaths
def createAddressDB():
'''
Generate the address database
types:
1: I2P b32 address
2: Tor v2 (like facebookcorewwwi.onion)
3: Tor v3
'''
if os.path.exists(dbfiles.address_info_db):
raise FileExistsError("Address database already exists")
conn = sqlite3.connect(dbfiles.address_info_db)
c = conn.cursor()
c.execute('''CREATE TABLE adders(
address text,
type int,
knownPeer text,
speed int,
success int,
powValue text,
failure int,
lastConnect int,
lastConnectAttempt int,
trust int,
introduced int
);
''')
conn.commit()
conn.close()
def createPeerDB():
'''
Generate the peer sqlite3 database and populate it with the peers table.
'''
if os.path.exists(dbfiles.user_id_info_db):
raise FileExistsError("User database already exists")
# generate the peer database
conn = sqlite3.connect(dbfiles.user_id_info_db)
c = conn.cursor()
c.execute('''CREATE TABLE peers(
ID text not null,
name text,
adders text,
dateSeen not null,
trust int,
hashID text);
''')
c.execute('''CREATE TABLE forwardKeys(
peerKey text not null,
forwardKey text not null,
date int not null,
expire int not null
);''')
conn.commit()
conn.close()
return
def createForwardKeyDB():
'''
Create the forward secrecy key db (*for *OUR* keys*)
'''
if os.path.exists(dbfiles.forward_keys_db):
raise FileExistsError("Block database already exists")
conn = sqlite3.connect(dbfiles.forward_keys_db)
c = conn.cursor()
c.execute('''CREATE TABLE myForwardKeys(
peer text not null,
publickey text not null,
privatekey text not null,
date int not null,
expire int not null
);
''')
conn.commit()
conn.close()
return
def create_blacklist_db():
if os.path.exists(dbfiles.blacklist_db):
raise FileExistsError("Blacklist db already exists")
conn = sqlite3.connect(dbfiles.blacklist_db, timeout=10)
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE blacklist(
hash text primary key not null,
dataType int,
blacklistDate int,
expire int
);
''')
conn.commit()
conn.close()
create_funcs = [createAddressDB, createPeerDB,
createForwardKeyDB, create_blacklist_db]

View File

@ -20,16 +20,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os, shutil
import onionrplugins as plugins
from logger import log as logging
import logger
import filepaths
from utils.readstatic import get_static_dir
def setup_default_plugins():
# Copy default plugins into plugins folder
if os.path.exists(get_static_dir() + '/official-plugins/'):
names = [f for f in os.listdir(get_static_dir() + '/official-plugins/')]
if os.path.exists(get_static_dir() + '/default-plugins/'):
names = [f for f in os.listdir(get_static_dir() + '/default-plugins/')]
shutil.copytree(
get_static_dir() + '/official-plugins/',
get_static_dir() + '/default-plugins/',
plugins.get_plugins_folder(), dirs_exist_ok=True)
@ -38,9 +38,9 @@ def setup_default_plugins():
if not name in plugins.get_enabled_plugins():
plugins.enable(name)
else:
logging.error(
logger.error(
"Plugin source directory does not exist!" +
"Onionr needs plugins to be useful")
"Onionr needs plugins to be useful", terminal=True)
for name in plugins.get_enabled_plugins():
@ -50,5 +50,5 @@ def setup_default_plugins():
except FileExistsError:
pass
except Exception as e:
#logging.warn('Error enabling plugin: ' + str(e))
#logger.warn('Error enabling plugin: ' + str(e), terminal=True)
plugins.disable(name, stop_event = False)

View File

@ -8,8 +8,9 @@ import base64
import ujson as json
import config
from logger import log as logging
import logger
import onionrvalues
from logger.settings import *
from utils import readstatic
"""
This program is free software: you can redistribute it and/or modify
@ -36,3 +37,42 @@ def setup_config():
config.save()
config.reload()
settings = 0b000
if config.get('log.console.color', True):
settings = settings | USE_ANSI
if config.get('log.console.output', True):
settings = settings | OUTPUT_TO_CONSOLE
if config.get('log.file.output', True):
settings = settings | OUTPUT_TO_FILE
set_settings(settings)
verbosity = str(config.get('log.verbosity', 'default')).lower().strip()
if not verbosity in ['default', 'null', 'none', 'nil']:
map = {
str(LEVEL_DEBUG) : LEVEL_DEBUG,
'verbose' : LEVEL_DEBUG,
'debug' : LEVEL_DEBUG,
str(LEVEL_INFO) : LEVEL_INFO,
'info' : LEVEL_INFO,
'information' : LEVEL_INFO,
str(LEVEL_WARN) : LEVEL_WARN,
'warn' : LEVEL_WARN,
'warning' : LEVEL_WARN,
'warnings' : LEVEL_WARN,
str(LEVEL_ERROR) : LEVEL_ERROR,
'err' : LEVEL_ERROR,
'error' : LEVEL_ERROR,
'errors' : LEVEL_ERROR,
str(LEVEL_FATAL) : LEVEL_FATAL,
'fatal' : LEVEL_FATAL,
str(LEVEL_IMPORTANT) : LEVEL_IMPORTANT,
'silent' : LEVEL_IMPORTANT,
'quiet' : LEVEL_IMPORTANT,
'important' : LEVEL_IMPORTANT
}
if verbosity in map:
set_level(map[verbosity])
else:
logger.warn('Verbosity level %s is not valid, using default verbosity.' % verbosity)

View File

@ -6,7 +6,7 @@ from threading import Thread
from uuid import uuid4
from time import sleep
from logger import log as logging
import logger
def _onionr_thread(func: Callable,
@ -18,10 +18,10 @@ def _onionr_thread(func: Callable,
try:
func(*args, **kwargs)
except Exception as _: # noqa
logging.warn(
logger.warn(
f"Onionr thread exception in {thread_id} \n" +
traceback.format_exc(),
)
terminal=True)
sleep(sleep_secs)

View File

@ -0,0 +1,22 @@
from typing import NewType
UserID = NewType('UserID', str)
UserIDSecretKey = NewType('UserIDSecretKey', str)
LoopBackIP = NewType('LoopBackIP', str)
DeterministicKeyPassphrase = NewType('DeterministicKeyPassphrase', str)
Ed25519PublicKeyBytes = NewType('Ed25519PublicKeyBytes', bytes)
BlockHash = NewType('BlockHash', str)
OnboardingConfig = NewType('OnboardingConfig', str)
# JSON serializable string. e.g. no raw bytes
JSONSerializable = NewType('JSONSerializable', str)
# Return value of some functions or methods, denoting operation success
# Do not use for new code
BooleanSuccessState = NewType('BooleanSuccessState', bool)

9
src/onionrusers/README.md Executable file
View File

@ -0,0 +1,9 @@
# onionrusers
onionrusers is a small collection of classes for interacting with onionr public keys, such as encrypting messages to them with forward secrecy, interacting with their settings, or else.
## Files
onionrusers.py: OnionrUsers class can be used to encrypt/decrypt messages to a particular Onionr user (incl. forward secrecy), view information about them, and get our friend list.
contactmanager.py: Inheriting from OnionrUsers, ContactManager allows arbitrary information to be associated with an Onionr user.

Some files were not shown because too many files have changed in this diff Show More