Wrote the starting card decks for CaoCao Liubei and SunQuan in typescript! It follows a centralized structure where all of the cards will be sourced from index.ts
Log in to leave a comment
Wrote the starting card decks for CaoCao Liubei and SunQuan in typescript! It follows a centralized structure where all of the cards will be sourced from index.ts
Log in to leave a comment
Wrote liubei cards! will elaborate later!
Log in to leave a comment
Currently I am writing cards that will go into liubeis deck, its a really long process icl
Log in to leave a comment
Finished making caocaos basic deck and now thinking of upgrade camp nodes on the map where you can upgrade a card to ‘plus status’ like in STS
Log in to leave a comment
Wrote a bunch of ts for caocaos “deck” and what I envision the gameplay to be, I am aiming for something similar to slay the spire in terms of mechanics and a RPG/alt history outcome that depending on what choices you make, your deck will evolve and so will your fictional endings will occur!
Log in to leave a comment
Debugging the nodes! Devlogs later at the end, ALMSOT DONE
Log in to leave a comment
Fixed a lot of issues and added multiple extra features for the .exe file as well as updated the readme for the complete workflow of new features. Test cases were also made as well as changes to the math and the cryptography algorithms coded in the project. Happy testing!
Log in to leave a comment
Devlog soon
Log in to leave a comment
Update later, almost dolne!!!!
Log in to leave a comment
will add devlog later ref number devlog 11
Log in to leave a comment
I built EntropyGarden and I actually understand cryptography now
Basically I made a system where two people can generate the exact same secret key from the same image without ever communicating. No servers, no key exchange, no middleman, nothing to intercept. It’s literally just image -> entropy -> HKDF -> same key on both sides. The key never gets sent anywhere but can travel to both parties
I didn’t just use a crypto library either (other than for failback) , this is around 3100 lines of pure Python built from scratch. I implemented Ed25519 for signatures, X25519 for key exchange, the Curve25519 math itself, HKDF, QR code generation, even Reed Solomon error correction. Then I wrapped everything in an interactive menu so it’s actually usable and not just some painful command line script. You can export keys as PEM, SSH, JSON, JWK or even QR codes, and the whole thing runs completely offline.
The process pretty rough. I started thinking how hard can parsing pixel data be and then immediately got destroyed by modular arithmetic. At some point elliptic curves just randomly clicked and after that things started making sense. Getting it to pass RFC 8032 test vectors was the moment I realized this actually works. Then somehow I turned it into a usable exe which was not even the original plan.
What I realized is cryptography isn’t magic, it’s just math plus being extremely careful. You can actually read the specs and implement this yourself if you’re willing to struggle through it. I had to deal with constant time operations, finite field arithmetic, and debugging things that don’t crash but are just wrong. Also QR codes are way more complicated than they look for no reason.
This isn’t just a random project either. You could use this for air gapped key generation, offline secure messaging, or cold storage. And the fact that the key never even gets transmitted makes it feel like an actual project that could see some real use for air gapped situations or setups!
The best part is I didn’t just use cryptography, I actually understand what’s going on now. I read the RFCs, implemented everything, tested it properly, and built something that genuinely works. That feels very different from just importing a library and hoping for the best.
Finalized everything, updated the CLI and added more functionalities, removed subscripts and updated the readme, basically delinting before shipping for review! Also note that bigger PNG files that are more clear will also take a longer time to get decoded :>. Currently the ASCII will be converted to a scannable PNG of the QR code instead since the resolution is not really clear even with the Reed
Log in to leave a comment
Also please note that PNGs that are bigger will naturally take the algorithm a longer time to decode into glyphs, please be patient!!!!
Tested all functionalities, and tested my test cases and everything works PERFECT! Probably have to do some touch ups on the CLI because i forgot an interface for the subcommands and other functions like signing messages digitally and HMAC challenge and response
Log in to leave a comment
Moved into QR code generation and this ended up being way deeper than expected because I didn’t use any libraries. Basically had to rebuild the entire QR encoding pipeline from the spec.
Started with understanding the format itself. QR codes aren’t just random squares, they have strict encoding modes depending on the data type, plus different versions that control grid size. Also had to choose an error correction level, which determines how much of the QR can be damaged and still recover the data. I went with higher correction because this is for keys, so reliability matters more than density.
Then came error correction which is where things got really technical. QR codes use Reed Solomon codes, which operate over Galois Field arithmetic instead of normal integers. That means addition becomes XOR and multiplication follows polynomial rules modulo an irreducible polynomial. I had to implement finite field multiplication manually, bit by bit, shifting and reducing using the field polynomial. This is the kind of math that looks simple on paper but is extremely easy to mess up in code. One wrong operation and the entire QR becomes unreadable.
After generating error correction codes, I had to interleave the data and parity blocks exactly as specified. This is not just concatenation since the bytes are arranged in a very specific pattern to distribute redundancy across the QR. Then came placing everything into the grid. QR codes have fixed function patterns like finder squares, timing lines, and format bits that all have to be placed at exact coordinates. The actual data bits are then woven through the remaining space in a zigzag pattern. This part felt like solving a binary puzzle where every bit position matters.
Finally built the rendering layer. Took the binary matrix and mapped it to Unicode block characters so it can be displayed directly in the terminal. Had to make sure spacing and proportions stay readable in monospace fonts, otherwise scanners won’t pick it up. The end result is a fully scannable QR code rendered as text, carrying cryptographic key material with built in error correction.
At this point I’ve basically reverse engineered and reimplemented QR encoding from scratch, including finite field math, error correction, and layout logic. No external libraries, just pure Python and elbow grease hah!
Log in to leave a comment
Moved into export and interoperability, basically turning raw keys into formats that real systems actually understand instead of just bytes sitting in memory.
First was PEM and PKCS#8. That meant taking the private key, wrapping it in ASN.1 DER structures, then base64 encoding it with proper headers like BEGIN PRIVATE KEY. Sounds simple until you realize Python doesn’t give you a native DER encoder, so I had to manually build the structure byte by byte. Length fields, type identifiers, all that low level encoding. Once it worked, the key could be dropped straight into OpenSSL or SSH tooling which is a huge step from just having raw entropy derived keys.
Then I implemented OpenSSH format. This one is more structured than it looks. There’s a magic header string, followed by fields describing the cipher and KDF. I supported both unencrypted keys and the structure needed for passphrase protection using bcrypt as the KDF. The final output matches what OpenSSH expects, meaning the keys generated from an image can actually authenticate against a real server.
Added JSON Web Key support next. This is more for web systems and APIs. Keys are represented as JSON with fields like kty and then base64url encoded values. I also added custom metadata fields so the key carries context about where it came from. It’s basically making the same deterministic keys portable across web based systems.
Then I somewhat built the QR code output which is probably the most fun part. Took the public key, encoded it into a QR matrix with error correction (super proud of that too btw), then rendered it directly in the terminal using block characters. Even if part of it is damaged or cropped it can still be recovered because of Reed Solomon encoding. So now you can literally scan a key off the terminal screen which is really convenient :).
Also added a raw binary format for internal use. Just the key bytes with a checksum prefix in big endian. No overhead, minimal storage, fast to read and write. This is what everything else builds on top of.
On top of all formats I added metadata tracking so keys aren’t just anonymous blobs. Each key now carries a timestamp of when it was derived, the exact derivation path used, the hashing algorithm, the original image source, and orientation data so the same image always maps correctly. There’s also a checksum field for integrity verification so corrupted keys can be detected immediately.
Log in to leave a comment
Basically wrote a few tests for my program to debug and managed to generate my first QR code from native ASCII
Log in to leave a comment
Today I basically implemented RFC 8032, Ed25519 , EdDSA signatures in pure Python and coded the edwards curve (in its twisted form) from scratch where it was basically
Curve equation: -x^2 + y^2 = 1 - (d)x^2y^2 where d = -121665/121666
Complete addition formulas (with no exceptions for point-at-infinity)
Fast doubling and addition with optimization
Did I mention it was all from scratch btw :)
I also did point decoding and encoding
32-byte encoding of points (64-bit y-coordinate + 1-bit x-sign)
Bit manipulation for sign recovery and reconstruction
Little-endian encoding per RFC 8032 standards which I studied overnight :/
Then I also implemented SHA-512 Hashing where I decided to use pythons hashlib which is just one external dependancy, and also created the 64 byte digest creation and did the prefix and nonce clamping for deterministic signatures.
I also wrote my own signature verification module down below which I am super proud of because the math involved was on another level! I hope this project gets high cookies because this project is super technical!
Log in to leave a comment
Moved into the actual crypto primitives and this is where it stopped being “deriving keys” and started being building real cryptographic functionality from scratch
First was Ed25519 key generation. Instead of generating random keys, I’m feeding in 32 bytes from the HKDF output, so the entire keypair is deterministic from the image. Those 32 bytes become the seed, then I process it. So tldr it means hashing it, splitting it, and clamping the private scalar so it fits the curve requirements. From there I do point multiplication on the Edwards curve to derive the public key. End result is a full Ed25519 keypair that can be regenerated anytime from the same entropy source. I also keep both the processed scalar and the original seed so nothing is lost and everything stays reproducible.
Then I implemented X25519 Diffie Hellman which is a completely different curve form but built on the same underlying math. Here the private key also comes from deterministic entropy, gets clamped according to RFC 7748, and then used in scalar multiplication against the base point to produce a public key. The key detail is using the Montgomery ladder which keeps the operation consistent and avoids leaking information through timing differences. Everything operates on the x coordinate only, which simplifies things but also means you have to be very precise with the math.
Once both sides generate their keypairs, the exchange is straightforward but kind of insane conceptually. Each side sends their public key, then uses their private key with the other party’s public key to compute a shared secret. Even though both sides are doing different calculations, they land on the exact same 32 byte result. No secret is ever transmitted, it just emerges on both ends independently.
That raw shared secret then goes back through HKDF to normalize it into usable key material. So even the output of the Diffie Hellman step gets structured the same way as everything else in the system.
At this point the system isn’t just generating keys from images anymore. It can produce signing keys that follow real standards and also perform secure key exchange almost like, dare I say like modern messaging protocols. All of it deterministic, all of it reproducible, and all of it built directly on top of the entropy extracted earlier.
Log in to leave a comment
Next part was building the actual entropy source from images, specifically PPM P6 files. The goal here was to turn an image into a reliable stream of randomness without doing anything sketchy or lossy.
PPM P6 format imo is perfect for this because it’s basically raw RGB in binary form. No compression with no weird encoding layers, just a header and then straight pixel bytes. So I wrote a parser that reads the header, extracts width, height, and max color value, then pulls the pixel data directly. I had to be really careful with how the bytes are interpreted because you’re dealing with raw binary, so if you mess up ordering or offsets everything downstream becomes garbage, this iteration took maybe 1 and a half hours +- including testing.
Once I had the pixel data, I didn’t just dump it directly into the system. I experimented with multiple ways of extracting entropy because raw pixel data can have patterns depending on the image. The simplest method is just concatenating all the bytes, which gives you a big pool of data but might include bias if the image has large uniform areas. So I added diagonal sampling where I only take pixels along certain paths across the image to reduce structured patterns to make the input much less predictable. Then I implemented somemixing like XORing segments and generating checksums to break up correlations and spread entropy more evenly.
Also added some guardrails so the system doesn’t accept garbage input. There’s a minimum image size requirement, around 96 by 96, because anything smaller just doesn’t give enough entropy to be meaningful. That ensures we’re working with at least tens of thousands of bytes instead of something tiny and predictable which should be the basis for entropy.
Another thing I accounted for is reproducibility. If someone rotates or flips the image, the raw byte order changes, which would produce completely different keys. So I track orientation metadata so the same logical image always maps to the same entropy regardless of how it’s stored or displayed, this took me quite some time ~ 2 hours
Finally added checksum validation on the file structure to make sure the parser isn’t silently accepting corrupted or malformed files. If the format isn’t exactly what’s expected, it fails early instead of feeding bad data into the pipeline and notifies the user.
At this point the system isn’t really grabbing bytes from an image, it’s actually treating the image as a structured entropy source with validation, normalization, then creating keys from them which I am super proud of!
Log in to leave a comment
So basically in this devlog I have created the failback systems in case my python homebrew implementation could not handle the requiremements after a given time of processing.
I did:
I also did some benchmarking and I found out that unsurprisingly
Ed25519 Signature Generation:
My implementation of pure python: ~4.5ms per signature
With cryptography lib: ~2.2ms per signature
Improvement: 2.4 with the cryptography lib but its essentially unnoticable by the average human
X25519 Key Exchange:
My implementation of pure python: ~3.8ms per scalar mult
With cryptography lib: ~1.8ms per scalar mult
Improvement: 2.11x
Hash Computation (HKDF):
Both: ~0.85ms (Python hashlib used in both)
I also implemented a graceful degredation process when cryptography is unavailable. Its just way too technical and complicated to talk about in this limited character pool :/
Log in to leave a comment
First thing I implemented today was HKDF based on the RFC 5869 standard. At a high level it’s basically a two stage pipeline that takes messy entropy and turns it into clean, structured keys. The extract phase takes whatever entropy I got from the image and runs it through HMAC with a salt.
This step is really important because raw entropy isn’t always evenly distributed, so this compresses it into a fixed, high quality pseudorandom key. Think of it like taking noisy input and normalizing it into something cryptographically usable for our use case scenario yk.
Then comes the expand phase. Instead of just producing one key, I can stretch that extracted key into as many bytes as I want. It does this by repeatedly running HMAC in a loop with a counter (self implemented btw) and then chaining outputs together. So I can deterministically generate multiple keys from the same source without ever touching randomness again. The “info” parameter is the key detail here because it acts like a label. Different info strings produce completely different outputs even if the base entropy is identical. That’s how I enforce domain separation, meaning one key can’t accidentally collide with another use case from almost the same image per se.
After that I built a fully native BIP32 style hierarchical system on top of HKDF. Instead of just getting one key per image, I now have a full tree of keys derived from a single seed. The image entropy becomes the master seed, and from there I can derive paths like m/44’/0’/0’ or m/44’/0’/1’. Each step in the path feeds into HKDF again using a path specific info string like entropygarden plus the path itself. That means every node in the tree is cryptographically isolated but still deterministically linked back to the original image.
What this really means in practice is that one image can generate an entire structured key hierarchy. Same image always gives the same tree, but different paths give completely different keys. So now there is no abstract randomness, no storage needed, and everything is reproducible on demand. It’s basically turning an image into a deterministic key generator with infinite branches which would mean that it would be unguessable from an adversaries perspective, while being fully reproducible by someone you want to share with key with!
Log in to leave a comment
What I did today : Implement Montgomery curve arithmetic without external libraries all the way from scratch which required me to look up the math for it and implement it in python logic.
I also implemented field arithmetic*(Modular Prime Field 2^255-19):
x^(p-2) mod pand widely used in cryptographyThen as I stated before, I also implemented the Montgomery Ladder(Key Exchange) where basically:
k·G where k is secret, G is generatorI have also studied clamping and what it does and how to implement it to the standards of RFC 7748
Overall it might not seem a lot but there is SOOO much math involved and a lot of trial and error
Log in to leave a comment
I built CommitForge which is a single-command CLI that scans your git working tree, catches mistakes before you commit such as debug prints, TODOs, hardcoded secrets, missing tests), suggests a proper conventional commit message, and
generates a clean HTML report you can share with your team before commiting, did I mention it is fully offline?
The hardest part was making the output actually useful. Early versions just said “file changed” which tells you nothing. I had to parse the raw git diff to detect added/removed functions, classes, and imports, then cross-reference that with pre-commit checks on the actual file content. Getting the signal-to-noise ratio right took the most iteration so I kept adding checks that were either too granular (tracking every import change) or too broad (scanning the entire repo instead of just changed files).
Finished my project for the locked in challenge, I am aware I did go over the 10 hour mark for devlogs though but it was a lot of work and I did not want to do much context switching.
Built CommitForge during a hackathon-style sprint which is a CLI tool that scans your repo, tells you what you’re about to commit, catches obvious mistakes, and suggests a proper commit message, all in one command. I started by setting up a clean project structure and locking in core dataclasses early so everything stayed stable. The initial version had multiple commands and worked fine, with config loading from .commitforge.json and about 29 tests passing, but the output was useless since it just said files changed. I rewrote the analyzer to actually parse git diffs, so it could report meaningful changes like added functions, then added checks for debug prints, TODOs, secrets, and missing tests, plus a clean HTML report that opens automatically.
On the second day, I focused on usability issues. The tool wasn’t scanning untracked files, which is when you need it most, so I fixed that. Commit suggestions were also bad, so I improved them to follow proper Conventional Commits like feat(auth): add password validation. I reduced noise by only analyzing changed or new files and limiting warnings to what actually matters. Finally, based on feedback, I simplified everything into a single drag and click pipeline. I removed unnecessary features like the GUI and overly granular checks, cleaned up the codebase, and ended with 39 passing tests. Tested it on a random project, got clean and useful output, and shipped it.
Log in to leave a comment
My objective of this project is to design a system that derives cryptographic keys deterministically from image entropy, enabling “visual key generation” where visual chaos in bytes becomes cryptographic order.
The stuff I identified as key challenges:
Pre learning that I probably have to do :
So likely this is what I have to do :
Layer 1: Image Entropy - PPM file parsing, pixel extraction
Layer 2: Key Derivation - HKDF-SHA3, hierarchical paths (m/44/0/0/…)
Layer 3: Cryptography with Ed25519 signing, X25519 DH, Curve25519 math
Layer 4: Export/Use - PEM, SSH, JSON, JWK, QR, Binary formats
Log in to leave a comment