TALON:
This is long, please read, then if you have read it all and want to flame that's okay.
I'll post my disclaimer up front. AI was used in the creation of this program to fill in my own knowledge gaps, but it doesn't mean I didn't try to learn what it did and why. It also generated much of the documentation. This is because I am not a native English speaker, but the thoughts are mine. AI merely translated them. I have taken the night to write this, and have tried to get my grammar correct, but there may be some mis-steps. If you read, you will say "Oh thank goodness the user-guides were made with AI"
Reticulum and it's cryptographic standards are used for the transport layer. This is done by calling the API in accordance with RNS technical documentation. All data transport is handled by Reticulum. Thank you to Mark, and Zenith and all the other maintainers.
The local database is decrypted using the user's passphrase. Encrypted at rest, decrypted on use.
keystore.py uses
os.random(ARGON2_SALT_LEN)
to generate the random salt. The salt is stored at 0o600, which I researched as the correct octal address to store such things. The salt is used in conjunction with the passphrase to generate the database key. I understand this is to help increase password complexity.
It does not help if the database is stolen. I protect against this by implementing a soft lease. If the client has not connected to the server in the last 24 hours, then Servernethandler.py rejects the client's request and tears down the RNS link until the server operator renews the lease manually. If an client device is suspected compromised, the server operator can revoke the lease entirely, which permanently tears down the link and destroys and overwrites that client's identity. This has in my mind some shortcomings, mostly being the local db can still be unlocked with the passphrase. I intend on using per client keys to mitigate this, meaning even with passphrase, the keys from the server would be needed to decrypt data. Those keys would then be rotated to remaining members if a client is revoked.
No encryption can protect against bad actors, which is why server operators must choose who has access. Just like messages screenshoted in a signal chat, a bad actor can copy information before revocation.
Back to normal flow though,
keystore.py then uses Argon2id to derive the 256-bit key from the user's passphrase
def derive_key(passphrase: str, salt: bytes) -> bytes:
Servers also generate an additional key for audit logs.
SQLcipher is used to unlock the database after Argon2id, however I was unable to get SQLCipher to work unless it was converted to raw hex string for PRAGMA, but this is not a security issue, it's just how SQLCipher needs the data. However, because the key needs to be in memory, this does make Talon vulnerable to having the key extracted while running, but no more than any other program.
All data is server readable, because the server operator is intended to be the mission coordinator
Other data that I thought might be more sensitive is encrypted with PyNaCl SecretBox prior to being stored in SQLCipher.
RNS identities are encyrypted with a BLAKE2b key derived from the DB key in indentiy.py
return hashlib.blake2b(
db_key,
digest_size=32,
person=b"TALONRNSIDv1".
salt=hashlib.sha256(_IDENTITY_KEY_DOMAIN).digest()[:16],
).digest()
then
payload - _IDENTITY_HEADER + encrypt_field(
identity.get_private_key(),
_identity_key(db_key),
)
Why? Because the RNS identity is essentially a network identity. It is my goal to provide a limit to identity impersonation if client.identity() were stole.
I used HMAC for RNS config acceptance, just as a tamper deterrent. Since Talon imports RNS, and uses RNS for all interfacing and routing I wanted something to prevent just swapping Talon onto a different config. This requires a derivation of the DB key to be able to alter the config. If the config file is altered outside of Talon, the SHA-256 won't match and Talon will refuse to start until the operator reviews and accepts. I should add that the config can only be edited once the db is unlocked.
Once again, if a bad actor changes the config, unlocks Talon and accepts, no encryption or security helps. Most database compromise is done from inside actors, not master hacker any how.
I've had a lot of fun making this, and have been working on it for almost a year. It started as just an i2p chat program over RNS. I have a lot of work I still want to do on it. I tried very hard to avoid the traditional traps of plaintext secrets, client side authentication and such. I do not understand Zenith saying I used AI to make my own cryptographic standards. I only call and employ existing standards in ways similar to other programs (I made my best effort to understand how programs like signal handle it), but maybe as I learn more I will see.
What it is - An application for group coordination. Use it for airsoft, or use it for mutual aid.
Maps- provide situational awareness. Operators can ping locations, create assets, sitreps or missions. Assets require 2 person verification. Missions require approval from server
Assets- People, caches, vehicles, safehouses, or build your own custom ones
Comms- Missions automatically create specific channels, servers can create rooms.
Radio - support for SDR radio ingest across a variety of profiles
Documents - upload/download documents, share with your team
Operator profiles - allows operators to edit their own profiles to highlight their skill sets
NomadNet - I had no justifiable reason for including this, and it does come with some security concerns but I like it. In the future I plan to build in a server proxy, so the server itself is the only thing touching NomadNet, and clients can browse pages via the server. The scaffolding for that is done.
Enrollment - Server generates the enrollment keys, the server I2P and Yggdrasil address can be encoded in the hash, so the client's RNS config will autogenerate.






You can git it here on my potato server. Pls no DOS me friends. It only runs on solar power and is not strong.
You can yell at me here: Cudanet@proton.me