64 Bits Or Less

0 views
Skip to first unread message

Mariela Laflam

unread,
Aug 4, 2024, 5:49:59 PM8/4/24
to viebecurjess
Ineed a SHA3-255 or 511. What if I simply truncate a standard SHA3-256 or 512? Apart from the doubled probability of hash collision, are there any other things I should be aware of? I could also truncate one byte instead of one bit, if useful.

Alternatively I could say that if the first byte, not bit, is 0xff, then the remaining ones represent something else. This should reduce the probability of hash collision, but what I would have a probability of 1/256 that a hash starts with 0xff, generating ambiguity in my encoding. I could say that if the for 4 bytes are 0xffffffff, then I would end up with probability of generating an ambiguous encoding of 1/2^32, but I would prefer having a well-defined encoding under any circumstances.


With all well-regarded hash functions, the bits of the hash all have equal worth: as far as anyone knows (unless they aren't telling), the bits are not correlated. If you take $k$ bits of an $n$-bit hash, you get a $k$-bit hash function. Truncating SHA-256 to 255 bits gives you a hash that's almost as good as SHA-256: it has $2^255$ strength against preimage attacks and $2^127.5$ strength against collision attacks.


There are precedents for taking certain bits of a hash. SHA-224 and SHA-384 are obtained with calculations that are essentially the same as SHA-256 and SHA-512 respectively, just with different initial values (which shouldn't matter to the strength of the algorithm) and with the output truncated to the smaller size. Another precedent is that UUID can be constructed from 122 bits of MD5 or SHA-1 hashes (out of 128 or 160 respectively).


For SHA3, there's a cleaner construction. Instead of taking SHA3-256 and cutting off one bit, take the SHAKE256 255-bit or 248-bit output. SHAKE256 is exactly the same as SHA3-256 except for two bits near the beginning of the calculation, so it has the same security properties, but it's explicitly designed to have variable-length output. You can even use SHAKE128 instead of SHAKE256, which is slightly cheaper to compute with no meaningful security loss.


It's unlikely that there's an actual security problem with truncating a hash, but using SHAKE gives you greater confidence that nothing will go wrong. Even better, to avoid domain collisions (where two parts of the system calculate the hash of the same string for different reasons), calculate the cSHAKE output with a unique string as the customization string.


Trimming is secure as long as the generic attacks are in good bounds. We require the hash functions to have avalanche criteria on the output bits, that is a change in the any of input bits must randomly affect half of the output bits. Each bit of the hash function must depend on the input bits; removing 1 bit or 1 byte doesn't affect the results of other bits.


Reducing hash output is common practice. Although maybe not a direct requirement, generally the output of a hash is considered indistinguishable from random - if the input is unknown, of course. So basically you can do with it what you want. The common thing to do is to take the leftmost bits or bytes of the hash output. You're taking the rightmost bits or bytes, and that's OK too.


As you already found out, trying to use one value out of 256 to indicate a special case is tricky. You can of course use set of bytes to escape values, but since your output size is static, you'll have to sacrifice more security for the special cases: the hashes starting with 0xFF in your case. As SHA3-512 has plenty of security, I'd just sacrifice a bit or even byte.


Finally, there is one rather odd issue with taking the leftmost bytes. You might get in trouble if you have other full hashes over the same data (the domain collision in Gilles' answer). To compensate for this, most hash functions have special bits or other constants when generating a shorter hash. Usually publishing the shorter hash is not a problem though. You could play it safe though and start off by hashing a specific magic value in advance, or by using SHAKE instead.


If the data is not a multiple of 64 bits, then I can use padding. I know that it is not secure. But if the key is less than or more than 64 bits, should I ask the user to enter the key again, or should I pad / truncate it?


If the "something else" you have might contain less than 56 bits of entropy (which is likely, if it's e.g. a user-chosen password), then you will most likely want a key stretching KDF such as PBKDF2. Such KDFs are deliberately slow (and their slowness is adjustable) to make brute force guessing attacks harder.


Also, please note that the 56-bit key size of plain DES is itself too short to resist brute force attacks using modern hardware, making DES insecure. If you can't use a more modern cipher like AES, you should at least use Triple DES, which doubles the effective key size of DES to 112 bits (at the cost of also tripling the work needed for encryption).


*) The standard way of storing a DES key is as a sequence of eight bytes, each consisting of 7 key bits and one redundant parity bit. Thus, the standard form of the key has 64 bits, even though only 56 of them are actually used for cryptographic purposes. This is a peculiarity of DES, not shared by most later block ciphers.


A slave device is going to wait until the clocks start coming again, basically hanging. The STM32's are not particularly flexible with SPI bit lengths. You could let the clocks stop/start, and then cut the 132 bits you're interested in out of the stream.


I can't see any indication in the datasheet that this is possible, and am assuming I'll have to bit-bang the interface, but thought I'd ask just in case there's some kind of magic that will allow me to use the native hardware.


However, assuming the slave device incorporates a simple shift register of length 20 bits, the sending more than 20 clock pulses will overflow the register, but this is potentially not a problem. Align the 20 data bits so that these are not the ones that overflow. For the usual operation of MSB sent first, the 20 bits would be right-aligned. The upper nybble of the first byte sent would be the overflow bits.


The assumption is that the data is strobed into the slave peripheral when the SS signal is raised. If the data is automatically strobed when a count of 20 bits is reached, a different approach would be required. In this case, the data would need to be left-aligned.


The part (a MAX6921 vacuum fluorescent display (VFD) driver) is designed to be cascaded, and only sets its outputs once a Latch Enable pin is pulsed - so sending unwanted bits FIRST will indeed do the job.


24 bits is giving you a higher dynamic range: you can store audio information until a level of -144dB FS instead of -96dB FS in 16 bits. That is the quality improvement you get, so the precision in dynamic range improves. This is useful if your recorded material is too soft, and you want to increase the volume while keeping the information in the less significant bits (i.e. the soft passages of the music) intact.


Recording in 24 bits does have two major drawbacks:1. The audio files consume 50% more disk space2. If your master needs to be 16 bits (i.e. if you are mastering to an audio CD) you need to add dithering noise to your recording in order to mask away rounding errors when truncating the least significant 8 bits.


There is one situation I can think of where 16 bits recording would be better: if you are going to record audio and you have no planning on increasing the volume at any point, so no faders > +0dB, no expanders, EQs, or anything else that can gain the signal. (Reverb is fine since it never increases the original signal strength). In this situation, using 24 bits has no additional value and you might as well save yourself the disk space and the dithering noise by recording directly on 16 bits.


During mixing, playback, and processing, ProTools increases your audio file's samples to its native stream format (which varies by the PT software/hardware you use), this internal stream is better than 24 bits. This stream is truncated when passed to the D/A - either by PT, or by the DAC.


If I encrypt strin of long varible text size to send over the air.When I get to the end of it I left with less then 128 bits.I don't want to add "0" till 128 because on teh other side I don't know there are not part of the text. Waht can I do?


From the datasheets "Load 128-bit data into AESADIN, or set the AESDINWR flag by software if the output data from a previous operation should be encrypted. When all 16 bytes are written, the AESDINWR flag indicates completion. The module starts encrypting the presented data when AESDINWR = 1."


Yes. That's the approach using block encryption. It is not good idea from security point of view to transmit less bits than encryption block size. You simply can't decrypt truncated block ;) Fixed value filler is bad idea either (because of predictability). I suggest to read AES papers - there's plenty of info about padding. If you'r lazy and don't wanna read then first padding byte after string shall be 0x00, then 0x01 and so on incrementally.


Is is possible to do the shiftOut() command with fewer than 8 bits? I am getting a digital pot working and it requires that I send it special groups of commands (1 bit then 7 bits then 7 bits). I want to do shiftOut to send these commands, as it does the whole clock pin thing. Is this possible? If I feed it only 1 byte will it only spit out 1 byte, or assume the rest are zeroes? Is there a suitable replacement command? Thanks!

3a8082e126
Reply all
Reply to author
Forward
0 new messages