So I designed a block chipher.
Because what can I do ?
No, seriously, what can I do ?! On one hand, the item that won (by fucking default) doesn't seem to be doing all that well ; on the other hand
In short -- there was not so much known demand for this category of item, and it missed out on the little that there was.
which yes fucking stands.
Think, by the way, think well and think hard on the meanings of The Day Of Failure and That Woman's Sadness, because what you do and what you don't do have consequences in the future. They do. They have consequences, and those consequences are indelible. There's no way to turn back time, there's no "make it be like it was before", there's no "as if X hadn't happened". There's no way out, and therefore it doesn't pay to stupid.i
So thenii : we could want a 256 bit key schedule, because that's what happens to have been specified in Eulora's communications protocol (latest restatement). However, since we're actually re-doing the whole symmetric cipher part there's no reason to import the idiocy we're replacing -- we could in principle have keys and blocks of any size we feel like.
Symmetric cipher blocks have however been specified at 1472 bytes, which would be a hard cap on the size of the key we're considering. These keys also have to be transported, however, and seeing how there's a 8 + 8 + 8 + 16 = 40 byte overhead for the packet transporting them and a further 4 bytes per key transported, it then follows we encounter the following constraints : we want the largest integer number which simultaneously
- Is smaller than 1472 and
- Together with 4 sums to a divisor of 1472-40 (1432)
- Is a divisor of 1472
The first constraint makes our keys fit inside pack ; the second constraint makes an integer count of keys neatly fit in a packet ; the third constraint makes packets neatly cipher with such a key.
Sadly, we quickly discover k = 1432 / (1472/q + 4) is not an integer for any useful integer values of q iii, meaning we will have to loosen either the 2nd or the 3rd constraint. It seems it's a lot easier to add some padding in a packet than to end up with partial blocks as part of packet ciphering, but let's lay out the options in detail :
If we make the key 736 bytes (q=2), we then can pack 1 key along with 696 bytes' worth of packing peanuts in a type 5.2 packet.
If we make the key 368 bytes (q=4), we then can pack 3 keys along with 328 bytes' worth of packing peanuts in a type 5.2 packet, a 300% (nominal) transport efficiency increase.
If we make the key 184 bytes (q=8), we then can pack 7 keys along with 144 bytes' worth of packing peanuts in a type 5.2 packet, a (further) 233% (nominal) transport efficiency increase.
If we make the key 92 bytes (q=16), we then can pack 15 keys along with 52 bytes' worth of packing peanuts in a type 5.2 packet, a yet further 214% (nominal) transport efficiency increase.
If we make the key 64 bytes (q=23), we then can pack 22 keys along with 24 bytes' worth of packing peanuts in a type 5.2 packet. The gains as to keycount possibly transported are dropping off, and moreover the padding/keysize proportion is optimal here, so therefore we hereby pick our key (and implicitly block) size : it will be 64 bytes, therefore a ciphered packet will consist of 23 blocks and type 5.2 packets will contain at most 22 keys. Done.
As far as implementation is concerned, our principal goal is to avoid key leakage. Therefore, the cipher will be implemented in the following manner :
1. For every bit of the key (in our case, 512 times) a ring buffer will be allocated of the same size as the message. In each of these buffers, the original message will be copied, at an offset incremented by one each time (so in the first buffer, the original message is copied starting at bit 0, whereas in the n-th buffer, the original message is copied starting at bit n). We will call these buffers "shitboxes", in loving memory of the Dounce's Confederacy tradition of calling things "S-boxes", as fucking if that hides anything.
2. The ciphered message is equal to the xor of the original message and all the registers which correspond to an offset at which the key bit is set.
I expect this procedure is reversible.iv
I also find this algorithm to be sufficiently confusing to me, and therefore secure.v
———- In this context, there's no difference between stupid and "independent". [↩]
- In the spirit of previous discussion. [↩]
- Which are anyways limited to powers of 2 up to 64 and the prime number 23. [↩]
- After a sufficient interval for lulz, I also provided the reversing method : seing how every bit of E, the enciphered message, is the result of the formula E[i] = P[i] xor K[1] * P[1] xor K[2] * P[2] xor ... xor K[j] * P[j] xor ... xor K[n] * P[n] (where P is the plaintext) it then follows that for any message of length n each bit of the enciphered message yields a similar equation, for a total of n of them.
As the count of unknowns (bits of P, P[j]) is also n, this then constitutes a system of n equations with n unknowns, which is determinate -- one has to merely reduce the matrix, and extract the original P. Meanwhile an attacker (lacking K, which is to say the bits K[1]...K[n]) instead faces a system of n equations with 2n unknowns.
Evidently this cipher is very vulnerable to P leakage (an attacker in possession of both P and E can derive K just as deterministically) and therefore somewhat vulnerable to E leakage (an attacker in possession of a sufficient pile of enciphered messages that he knows were produced with the same key can derive that key if he obtains some control bits from P -- such as for instance if he knows "all messages are ASCII", for instance) for which reason this Chipher cipher is not suitable for transmitting unpacked data (in fact key leakage and compressability of P correlate). [↩]
- This proclamation is required by the traditions of the ciphermaking industry. It is included lest someone misunderstand the situation and/or think this is not even a real cipher [↩]
Monday, 29 October 2018
http://btcbase.org/log/2018-10-29#1867216 for fyootoor ref.
Tuesday, 30 October 2018
Well, you do write great code, just... what can I say, not always for the right thing.
Tuesday, 30 October 2018
"E, the enciphered message, is the result of the formula E[i] = P[i] xor K[1] * P[1] xor K[2] * P[2] xor ... xor K[j] * P[j] xor ... xor K[n] * P[n] (where P is the plaintext)" -- I don't think this is correctly stated - or I don't get something in it. I think E(i) = P(i) xor (K*Reg)(1) xor (K*Reg)(2)... xor (K*Reg)(n) with Reg the matrix of registries and K*Reg the usual matrix multiplication.
With the example from the logs: K=(0,1,0,1) P=(1,1,1,0) and E(2)=P(2) xor P(3) xor P(1) = 1 xor 1 xor 1 = 1 but with the formula above it would be E(2)= P(2) xor 0*P(1) xor 1*P(2) xor 0*P(3) xor 1*P(4) = P(2) xor P(2) xor P(4) = 1 xor 1 xor 0 = 0 .
Tuesday, 30 October 2018
I wasn't multiplying matrices, but bit offsets.
"The i-th bit of E is obtained by taking the i-th bit of P, and xoring it with the product of the 1st bit of K and the 1st bit of P, and further xoring it with the product of the 2nd bit of K and the 2nd bit of P..." is what was contemplated.
Tuesday, 30 October 2018
For future record : this actually died the next day, leaving us lonelier and sadder than before.