kek padding
This commit is contained in:
+112
-1
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user