kek padding

This commit is contained in:
2023-04-01 00:12:49 -06:00
parent 5d02fb0865
commit b1b5b37515
+112 -1
View File
@@ -267,7 +267,19 @@ Just pay attention to the flow for now.
- We `squeeze/3` the `WetSponge` out to get the `ResultBits` - We `squeeze/3` the `WetSponge` out to get the `ResultBits`
```erlang ```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L166-L172 %% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L155-L172
-spec keccak(Capacity, Message, OutputBitLength) -> Digest
when Capacity :: pos_integer(),
Message :: bitstring(),
OutputBitLength :: pos_integer(),
Digest :: bitstring().
%% @doc
%% Note: this is Keccak 1600, the only one used in practice
%%
%% Capacity must be strictly less than 1600
%% @end
keccak(Capacity = _c, Message, OutputBitLength) -> keccak(Capacity = _c, Message, OutputBitLength) ->
BitRate = 1600 - Capacity, BitRate = 1600 - Capacity,
PaddedMessage = pad(Message, BitRate), PaddedMessage = pad(Message, BitRate),
@@ -280,6 +292,105 @@ keccak(Capacity = _c, Message, OutputBitLength) ->
The padding part is kind of dumb. `absorb/4` and `squeeze/3` both call The padding part is kind of dumb. `absorb/4` and `squeeze/3` both call
`inner_keccak/1`, which like I said is where all the real bit-churning happens. `inner_keccak/1`, which like I said is where all the real bit-churning happens.
### Padding
The absorption phase is "chunked", meaning
1. it consumes a chunk of the input bits
2. updates the state (the "sponge")
3. if there are no more input bits to consume, absorption is done
4. else, go to step (1)
The size of this chunk is called the `BitRate`. In order for this to work, the
bit length of the input has to be a multiple of `BitRate`. The padding step
exists to make sure that is true.
The padding rule is `/10*1/`, as in the regex. So for instance, suppose our bit
rate was `10`.
```
input (bytes) : 00000111 10101100 01001111
input (grouped into 10) : 0000011110 1011000100 1111______
padded input : 0000011110 1011000100 1111100001
```
The rules are
1. There will *always* be at least two bits of padding added to the end of the
bitstring
2. The first padding bit will be `1`
3. The last padding bit will be `1`
4. *If* there are intermediate padding bits, they will all be `0`
5. The total number of padding bits added is however many makes the length of
the resulting bitstring an integer multiple of the `BitRate`
With that in mind:
```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L176-L234
-spec pad(Message, BitRate) -> NewMessage
when Message :: bitstring(),
BitRate :: pos_integer(),
NewMessage :: bitstring().
%% @private
%% padding
%% divide the message into r-bit blocks
%%
%% the message ends with 1000...0001
%%
%% sha3 calls this /10*1/ as in the regex
%%
%% Reference: https://en.wikipedia.org/wiki/SHA-3#Padding
%% @end
% note: rem will always return a positive integer because both bit_size
% case when the message bit length is evenly divisible by the bit rate
% in this case we add a whole new r-word
pad(Message, BitRate = _r) when (bit_size(Message) rem BitRate) =:= 0 ->
% Suppose the BitRate was 8 and we had 0 bits left
% Input:
% Bits: <<>>
% Idx1: 12345678
% Result:
% Bits: 10000001
% Idx1: 12345678
% In this case we add a new r-word
NewRWord = <<1:1, 0:(BitRate - 2), 1:1>>,
NewMessage = <<Message/bitstring, NewRWord/bitstring>>,
NewMessage;
% this is the retarded case, when the bit length of the message is exactly one
% bit less than dividing the BitRate
pad(Message, BitRate = _r) when (bit_size(Message) rem BitRate) =:= (BitRate - 1) ->
% Suppose the BitRate was 8 and we had 7 bits left
% Input:
% Bits: ABCDEFG
% Idx1: 12345678
% Result:
% Bits: ABCDEFG1 00000001
% Idx1: 12345678 12345678
% in this case, we add a 1, (r-1) zeros, and a trailing 1
NewRWord = <<1:1, 0:(BitRate - 1), 1:1>>,
NewMessage = <<Message/bitstring, NewRWord/bitstring>>,
NewMessage;
% this is the general case, where there are at least 2 bits left in order to
% fill out the r-word
pad(Message, BitRate = _r) ->
% Suppose the BitRate was 8 and we had 3 bits left
% Input:
% Bits: ABC
% Idx1: 12345678
% Result:
% Bits: ABC10001
% Idx1: 12345678
NumberOfMessageBitsInTheLastRWord = bit_size(Message) rem BitRate,
NumberOfNewBitsNeeded = BitRate - NumberOfMessageBitsInTheLastRWord,
NumberOfNewZerosNeeded = NumberOfNewBitsNeeded - 2,
NewMessage = <<Message/bitstring, 1:1, 0:NumberOfNewZerosNeeded, 1:1>>,
NewMessage.
```
[german-lecture]: https://www.youtube.com/watch?v=JWskjzgiIa4 [german-lecture]: https://www.youtube.com/watch?v=JWskjzgiIa4
[german-lecture-notes]: https://www.crypto-textbook.com/download/Understanding-Cryptography-Keccak.pdf [german-lecture-notes]: https://www.crypto-textbook.com/download/Understanding-Cryptography-Keccak.pdf
[nist-standard]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf [nist-standard]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf