theta
This commit is contained in:
@@ -590,6 +590,7 @@ inner_keccak(Sponge) ->
|
|||||||
rounds(Sponge, 24).
|
rounds(Sponge, 24).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-spec rounds(Sponge, NumRoundsLeft) -> ResultSponge
|
-spec rounds(Sponge, NumRoundsLeft) -> ResultSponge
|
||||||
when Sponge :: <<_:1600>>,
|
when Sponge :: <<_:1600>>,
|
||||||
NumRoundsLeft :: non_neg_integer(),
|
NumRoundsLeft :: non_neg_integer(),
|
||||||
@@ -625,6 +626,102 @@ rnd(RoundIdx0, Sponge) ->
|
|||||||
iota(RoundIdx0, chi(pi(rho(theta(Sponge))))).
|
iota(RoundIdx0, chi(pi(rho(theta(Sponge))))).
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The Greek letter steps will often reference "the column to the front" or some
|
||||||
|
such. The details of this are described in the [coordinate system
|
||||||
|
section][coord-system]. For now, trust that the function `left/1` correctly
|
||||||
|
fetches the X-coordinate to our left, and worry about the details later.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Inner Keccak: Theta stage
|
||||||
|
|
||||||
|
Keep [the Greek letter pitfall][greek-letter-pitfall] in mind.
|
||||||
|
|
||||||
|
For each bit in the sponge:
|
||||||
|
|
||||||
|
1. take
|
||||||
|
|
||||||
|
- the bit
|
||||||
|
- the 5-bit column to the left
|
||||||
|
- the 5-bit column to the front right
|
||||||
|
|
||||||
|
in **the original array** (beware the [Greek letter pitfall][greek-letter-pitfall]!)
|
||||||
|
|
||||||
|
2. compute the parity of the concatenation; that is, in the concatenated
|
||||||
|
bitstring
|
||||||
|
|
||||||
|
- if the total number of `1`s is even, the parity is `0`
|
||||||
|
- if the total number of `1`s is odd, the parity is `1`
|
||||||
|
|
||||||
|
3. set the bit to that parity value from step (2)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```erlang
|
||||||
|
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L372-L444
|
||||||
|
|
||||||
|
-spec theta(Array) -> NewArray
|
||||||
|
when Array :: <<_:1600>>,
|
||||||
|
NewArray :: <<_:1600>>.
|
||||||
|
%% @private
|
||||||
|
%% the theta step
|
||||||
|
%% go bit by bit, applying a weird transformation to each bit
|
||||||
|
%% @end
|
||||||
|
|
||||||
|
theta(Array) ->
|
||||||
|
theta(Array, Array, 0).
|
||||||
|
|
||||||
|
|
||||||
|
-spec theta(Array, OldArray, Idx0) -> NewArray
|
||||||
|
when Array :: <<_:1600>>,
|
||||||
|
OldArray :: <<_:1600>>,
|
||||||
|
Idx0 :: 0..1599,
|
||||||
|
NewArray :: <<_:1600>>.
|
||||||
|
%% @private
|
||||||
|
%% the theta step
|
||||||
|
%% go bit by bit, applying a weird transformation to each bit
|
||||||
|
%% @end
|
||||||
|
|
||||||
|
% done
|
||||||
|
theta(ResultArray, _, 1600) ->
|
||||||
|
ResultArray;
|
||||||
|
% do the weird permutation
|
||||||
|
% x = left/right -/+
|
||||||
|
% y = down/up -/+
|
||||||
|
% z = outOfScreen/intoScreen -/+
|
||||||
|
% front/behind -/+
|
||||||
|
% left-handed coordinate system but what can you do
|
||||||
|
theta(ArrayBits, OrigArray, ThisIdx0) ->
|
||||||
|
<<Before:ThisIdx0, ThisBit:1, Rest/bitstring>> = ArrayBits,
|
||||||
|
{xyz, ThisX, _ThisY, ThisZ} = idx0_to_xyz(ThisIdx0),
|
||||||
|
XToTheLeft = left(ThisX),
|
||||||
|
XToTheRight = right(ThisX),
|
||||||
|
ZToTheFront = front(ThisZ),
|
||||||
|
ColumnToTheLeft = xzth({xz, XToTheLeft, ThisZ}, OrigArray),
|
||||||
|
ColumnToTheFrontRight = xzth({xz, XToTheRight, ZToTheFront}, OrigArray),
|
||||||
|
NewBit = parity(<<ColumnToTheLeft/bitstring, ColumnToTheFrontRight/bitstring, ThisBit:1>>),
|
||||||
|
NewBits = <<Before:ThisIdx0, NewBit:1, Rest/bitstring>>,
|
||||||
|
NewIdx0 = ThisIdx0 + 1,
|
||||||
|
theta(NewBits, OrigArray, NewIdx0).
|
||||||
|
|
||||||
|
|
||||||
|
-spec parity(Bits) -> Parity
|
||||||
|
when Bits :: bitstring(),
|
||||||
|
Parity :: 0 | 1.
|
||||||
|
%% @private
|
||||||
|
%% Count the number of 1s in the given bitstring. Return 0 if even, 1 if odd.
|
||||||
|
%% @end
|
||||||
|
|
||||||
|
parity(Bits) ->
|
||||||
|
parity(Bits, 0).
|
||||||
|
|
||||||
|
parity(<<0:1, Rest/bitstring>>, NOnes) -> parity(Rest, NOnes);
|
||||||
|
parity(<<1:1, Rest/bitstring>>, NOnes) -> parity(Rest, NOnes + 1);
|
||||||
|
parity(<<>> , NOnes) -> NOnes rem 2.
|
||||||
|
```
|
||||||
|
|
||||||
|
[coord-system]: #inner-keccak-coordinate-system
|
||||||
|
[greek-letter-pitfall]: #pitfall-greek-letter-steps-require-two-copies-of-the-sponge-to-compute
|
||||||
[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
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
Reference in New Issue
Block a user