A little update on CoinZdense development
As you may know the spq-sigs project has been renamed to 'CoinZdense'. It's not just a name-change. The mile-stones so far:
- A smaller more-manageable project definition derived from the old HIVE DHF proposal, no longer HIVE specific
- A first proof-of concept implementation in Python
- A prototype implementation in C++
After the 3th milestone, two things happened that changed the trajectory of the project:
- I spoke with a few capability-security people about the potential to about privileged vs unprivileged use of crypto primitives
- I looked into different possible attack scenarios and how to mitigate them.
key-derivation and entropy acquirement as privileged operation.
In both the Python POC as in the C++ prototype implementation, the spq-sigs library made extensive use of the system's entropy source by asking for random data strings. From a capability security least-authority point, allowing a piece of code to exhaust the entropy pool, even if the software is a cryptographic library, is considered a big no-no. Fortunately libsodium provides a usefull way around this with it's key-derivation API that allows a huge number of secret subkeys to be derived from a single high-entropy master key. All that is needed is for every place we need a unique secret key, that we can determine an equally unique 64 bit index number for that key.
For the multi-layer keys used by spq-sigs, every layer-key requires:
- Twice the amount of times the OTS-bits value is needed to get at at least the hash-length value for every signature, times the number of signatures the level-key can make (what whould be two to the power of the height value)
- Once for the level-key salt
In short:
Where:
- n : number of high entropy values needed for a key at this level
- l : hash-length parameter in bytes, this is a signing key global value
- o: otsbits parameter in bits, this is a signing key
- h: level-key merkle tree height parameter for a key at this level
Now as we have multiple level keys, and we know the number of instances we will eventualy have at the level just below the current one will be times the number of level keys at the current level, we can create a little algoritm that makes sure each level key gets exactly the number of indices it needs, without any chance of accidental index, and thus entropy reuse.
The great thing about this approach is that it isn't just a good idea from a least-authority perspective, it also allows us to maintain minimal state on the client side of things in order to be able to sync between multiple clients using the same key.
When integrating the code for unique index distribution into spq-sigs, the first signs of the initial API beginning to crack were starting to show. More on that later.
Mitigating attack scenarios.
One thing that is different about hash-based signatures compared to for example ECDSA signatures is that with hash-based signing, a signing key is an exhaustible resource. If you create a signing key that is meant to sign a million transactions, every signature you make will decrement the number of signatures you can still safely make after that. Think of it that every signature has a unique index and that index should be used only once.
There are two things we need to avoid that are specific to hash-based signatures:
- Reuse of the same signing index. The client(s) should try not to re-use, the server/blockchain should not accept re-use.
- Denial of service against the signing key-space. A bad actor should not be able to trick the client to exhaust its signing key resources.
There is a simple way both concerns can be addressed and mostly mitigated. Each client should store the index of its last produced and accepted signature, but also ash the server or blockchain for the latest known full signature as well, together with the hash of the last known signed transaction.
While the actual handshake protocol and specific security policies used by both client and blockchain or server fall outside the scope of the library, the API needs to be a good enough fit for this handshake setup and matching policies. Again, just like for the key derivation index generator, the original API for spq-sigs library.
Enter CoinZdense
Given the need for API changes, and given the code so far was just prototype for C++ and Proof Of Concept for Python, I decided that the name-change and the general API changes needed, plus porting the key-derivation to Python, should combine into a fresh start in a fresh new repo.
So now I'm working on the CoinZdense Python library in this new github repo. So where am I now in this?
- The key-derivation code has been ported.
- The signature format has been changed, slightly, to accommodate the handshake.
- There seems to be working signing code now. Not 100% sure because I will need working new-format validation code to test that first.
- The signing API is comming close to handshake compatibility.
So what does the API look like right now?
import coinzdense.signing
...
key = coinzdense.signing.SigningKey(hashlen=24,
otsbits=6,
heights=[2, 3, 4],
idx=sign_index,
password=b"What kind of dumb password is this?",
one_client=False
)
..
sig = key.sign_string("We need some silly string to sign", compressed=False)
..
with open("path/to/backup.json", "w") as bu:
bu.write( key.serialize(self))
Now with the backup, the next time we could do something like:
with open("path/to/backup.json") as bu:
backup = bu.read()
key = key = coinzdense.signing.SigningKey(hashlen=24,
otsbits=6,
heights=[2, 3, 4],
idx=sign_index,
password=b"What kind of dumb password is this?",
one_client=False
)
sig = key.sign_string("We need some silly string to sign", compressed=False)
..
with open("path/to/backup.json", "w") as bu:
bu.write( key.serialize(self))
So what's going on? the first thing we should know is the idx number is supposed to be the index from the lastsig signature provided by the server or blockchain to our client. When there is no backup yet, we have zero option than to trust there is no DOS going on, other than asking for user validation, but I'm not sure how acceptable that would be from a UID perspective.
The second time around though, we have a backup and we can apply some policies. The one_client boolean allows for some policy enforcement. If there is only one client with the signing key installed, then it should be unexpected to see a jump in the idx value, and an exception will be thrown. For the rest, policy enforcement is supposed to be handled outside of the library.
Next?
As stated, we need the validator up and running in order to implement the whole handshake from the client's perspective, and in order to allow for a server/blockchain perspective to be implemented as well. When the validator is working, it will be time to fine-tune the API and make a demo four way handshake setup that tests all scenario's I can come up with, just to test if a user of the coinZdense library will be able to implement useful policies without running into API caused issues or shortcommings.
Once the Python implementation works OK with the handshake setup, I'll be going back to C++ and make a C++ version of coinZdense as well.
The coinZdense website (help needed)
Currently the coinZdense website website looks like shit. I just made a github page and stole the lay-out from there, just to have something semi-decent. I've got 150 $HIVE that I am willing to spent on getting something better up and running. No programming and fancy stuff, just simple static site that branches out to github sub-projects and HIVE blog posts. But it needs to look like the project means business in helping to solve the QC thread for utility coins and DEX chains, and it needs to look decent and up-to-date on both mobile devices and on a PC. So if you can work with and can show me a tiny bit of what I could expect, please drop me a comment.
Tippingjar
This is still, other than some upvotes on HIVE, an unfunded project, but it is a project with a crypto typingjar. So if you ike the work I'm doing on this project, and you would like me to be able to allocate some more time resources on the project than I currently can, please consider tipping me some crypto through that page.
Discord
I'm not really active on Discord right now, but as it's the place to be for many of you, I created this Discord server for the project. The link doesn't expire, but there is a 100 usage limit (that I hope it won't reach). I hope in the future, when the project parts get more mature, that I can work with folks like (Python),
(C++),
(Python) and
(JavaScript) to see what would be needed to get the HIVE development eco system ready for a path towards quantum resistance, using coinZdense, but while I'm nowhere near that point right now, I hope you guys will join this server so when the time comes we can see if we can make things play nice for everyone.
Unfortunately Ruby, PhP and Typescript aren't on the roadmap for me, as for me there are now other chains to consider with a different language ecosystem involving Rust or Clojure, and as Monte is also an important target for me, so unless I can later find people willing to do a port to those languages, that might pose a problem for HIVE adoptation. Anyhow, all interesting subjects I'dd like to discuss on discord with anyone working on either the HIVE blockchain or on HIVE client libraries in different programming languages.