wrote up rho step

This commit is contained in:
2023-04-01 23:37:59 -06:00
parent 9a91d6782a
commit db6cffe92c
5 changed files with 159 additions and 0 deletions
+159
View File
@@ -34,6 +34,17 @@ special cases of Keccak.
### Pitfalls ### Pitfalls
#### Pitfall: This is only keccak-f-1600
Keccak has an "outer keccak" and an "inner keccak". The standard specifies
this free parameter called `b`, which is the bit size of the algorithm's state.
For what I needed, this can be assumed to be `1600`. You may need to
generalize this code. Hopefully this explainer is clear enough that you can do
that.
![NIST standard, pp. 17](./keccak-f.png)
#### Pitfall: "fast keccak" versus "clear keccak" #### Pitfall: "fast keccak" versus "clear keccak"
The main reference is the "clear" Erlang code. The "fast" version is the The main reference is the "clear" Erlang code. The "fast" version is the
@@ -722,11 +733,159 @@ parity(<<>> , NOnes) -> NOnes rem 2.
``` ```
### Inner Keccak: rho stage ### Inner Keccak: rho stage
This stage iterates over the `{X, Y}`-coordinate pairs, and applies an affine
shift to the remaining `Z`-coordinate.
![NIST standard, pp. 13](./rho.png)
The shifts are given by a table which is in a janky order because look how
smart we don't you get it it's modular arithmetic it means 4 and 3 are like
negative numbers I am so smart please tell me how smart I am
![NIST standard, pp. 13](./rho-table-wojak.png)
The outer part of this code `rho/1` and `rho/2` just contains the loopy part.
The actual transformation is in `rhoxy/2`. Erlang doesn't have loops. Instead
we pick a starting point...
```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L459-L467
-spec rho(Array) -> NewArray
when Array :: <<_:1600>>,
NewArray :: <<_:1600>>.
%% @private
%% do the rho step
%% @end
rho(Array) ->
rho(Array, {xy, 0, 0}).
```
Then on each step, update the `{X, Y}` value, with our branching logic to test
if we're done...
```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L471-L492
-spec rho(Array, LaneXY) -> NewArray
when Array :: <<_:1600>>,
LaneXY :: {xy, 0..4, 0..4},
NewArray :: <<_:1600>>.
%% @private
%% do the rho step to each lane
%% @end
% terminal case
rho(Array, XY = {xy, 4, 4}) ->
Result = rhoxy(Array, XY),
Result;
% need to reset Y and increment X
rho(Array, XY = {xy, X, 4}) ->
NewArray = rhoxy(Array, XY),
NewXY = {xy, X + 1, 0},
rho(NewArray, NewXY);
% need to increment Y and leave X
rho(Array, XY = {xy, X, Y}) ->
NewArray = rhoxy(Array, XY),
NewXY = {xy, X, Y + 1},
rho(NewArray, NewXY).
```
The actual transformation looks up the offset for the `{X, Y}` coordinate in a
table and applies it. `xyset/3` is a function that replaces a lane. This is
explained in the [coordinate system section.](#inner-keccak-coordinate-system).
```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L496-L517
-spec rhoxy(Array1600, LaneXY) -> NewArray1600
when Array1600 :: <<_:1600>>,
LaneXY :: {xy, 0..4, 0..4},
NewArray1600 :: <<_:1600>>.
%% @private
%% do the rho step to a given lane
%% @end
rhoxy(Array, ThisXY = {xy, ThisX, ThisY}) ->
ThisOffset = offset(ThisX, ThisY),
ThisLane = xyth(ThisXY, Array),
% we increase the z coordinate by the offset
% Suppose the offset is 2
% bits = A B C D E
% z = 0 1 2 3 4
% newbits = D E A B C
% in other words, we take Offset number of bits off the tail of the lane
% put them on the front
<<Foo:(64 - ThisOffset), Bar:ThisOffset>> = ThisLane,
NewLane = <<Bar:ThisOffset, Foo:(64 - ThisOffset)>>,
NewArray = xyset(ThisXY, Array, NewLane),
NewArray.
```
The `offset/2` table is copied from the table on pp. 13 of the NIST
specification. The reason for the `rem 64` is that our lane depth is `64`
because [we're not implementing full generalized
keccak](#pitfall-this-is-only-keccak-f-1600), we're only implementing the
keccak that is actually used in SHA-3 and SHAKE.
```erlang
%% https://github.com/pharpend/kek/blob/8a8a655a80c26ae32763cc25f1e0df8ab0653c82/kek.erl#L521-L558
-spec offset(X, Y) -> Offset
when X :: 0..4,
Y :: 0..4,
Offset :: 0..63.
%% @private
%% See NIST specification, pg. 21
%% @end
offset(3, 2) -> 153 rem 64;
offset(3, 1) -> 55 rem 64;
offset(3, 0) -> 28 rem 64;
offset(3, 4) -> 120 rem 64;
offset(3, 3) -> 21 rem 64;
offset(4, 2) -> 231 rem 64;
offset(4, 1) -> 276 rem 64;
offset(4, 0) -> 91 rem 64;
offset(4, 4) -> 78 rem 64;
offset(4, 3) -> 136 rem 64;
offset(0, 2) -> 3 rem 64;
offset(0, 1) -> 36 rem 64;
offset(0, 0) -> 0 rem 64;
offset(0, 4) -> 210 rem 64;
offset(0, 3) -> 105 rem 64;
offset(1, 2) -> 10 rem 64;
offset(1, 1) -> 300 rem 64;
offset(1, 0) -> 1 rem 64;
offset(1, 4) -> 66 rem 64;
offset(1, 3) -> 45 rem 64;
offset(2, 2) -> 171 rem 64;
offset(2, 1) -> 6 rem 64;
offset(2, 0) -> 190 rem 64;
offset(2, 4) -> 253 rem 64;
offset(2, 3) -> 15 rem 64.
```
### Inner Keccak: pi stage ### Inner Keccak: pi stage
### Inner Keccak: chi stage ### Inner Keccak: chi stage
### Inner Keccak: iota stage ### Inner Keccak: iota stage
### Inner Keccak: coordinate system ### Inner Keccak: coordinate system
[coord-system]: #inner-keccak-coordinate-system [coord-system]: #inner-keccak-coordinate-system
[greek-letter-pitfall]: #pitfall-greek-letter-steps-require-two-copies-of-the-sponge-to-compute [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
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB