more kekking
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
%% @doc
|
%% @doc
|
||||||
%% References
|
%% References
|
||||||
%% 1. Helpful lecture: https://www.youtube.com/watch?v=JWskjzgiIa4
|
%% 1. Helpful lecture: https://www.youtube.com/watch?v=JWskjzgiIa4
|
||||||
|
%% Notes: https://www.crypto-textbook.com/download/Understanding-Cryptography-Keccak.pdf
|
||||||
%% 2. NIST standard: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
%% 2. NIST standard: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
%% (btw: the double bar notation means "concatenate")
|
%% (btw: the double bar notation means "concatenate")
|
||||||
%% 3. https://en.wikipedia.org/wiki/SHA-3
|
%% 3. https://en.wikipedia.org/wiki/SHA-3
|
||||||
@@ -261,6 +262,7 @@ absorb(<<>>, _r, _c, FinalSponge) ->
|
|||||||
FinalSponge.
|
FinalSponge.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-spec squeeze(WetSponge, OutputBitLength, BitRate) -> ResultBits
|
-spec squeeze(WetSponge, OutputBitLength, BitRate) -> ResultBits
|
||||||
when WetSponge :: <<_:1600>>,
|
when WetSponge :: <<_:1600>>,
|
||||||
OutputBitLength :: pos_integer(),
|
OutputBitLength :: pos_integer(),
|
||||||
@@ -571,8 +573,8 @@ offset(2, 3) -> 15 rem 64.
|
|||||||
|
|
||||||
pi(Array1600) ->
|
pi(Array1600) ->
|
||||||
% what I'm going to make is a map #{{xy, X, Y} := Lane}
|
% what I'm going to make is a map #{{xy, X, Y} := Lane}
|
||||||
% then make a new lane map from the original
|
% then make a new map from the which applies the coordinate transformation
|
||||||
% then convert it back into
|
% then convert it back into an array
|
||||||
OriginalLaneMap = lane_map(Array1600, #{}, {xy, 0, 0}),
|
OriginalLaneMap = lane_map(Array1600, #{}, {xy, 0, 0}),
|
||||||
NewLaneMap = new_lane_map(OriginalLaneMap, #{}, {xy, 0, 0}),
|
NewLaneMap = new_lane_map(OriginalLaneMap, #{}, {xy, 0, 0}),
|
||||||
NewArray1600 = lane_map_to_arr1600(NewLaneMap, <<0:1600>>, {xy, 0, 0}),
|
NewArray1600 = lane_map_to_arr1600(NewLaneMap, <<0:1600>>, {xy, 0, 0}),
|
||||||
@@ -703,8 +705,51 @@ lane_map_to_arr1600(LaneMap, Array1600Acc, ThisXY = {xy, X, Y}) ->
|
|||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
chi(_Sponge) ->
|
|
||||||
error(nyi).
|
-spec chi(Array1600) -> NewArray1600
|
||||||
|
when Array1600 :: <<_:1600>>,
|
||||||
|
NewArray1600 :: <<_:1600>>.
|
||||||
|
%% @private
|
||||||
|
%% The chi step. The following transformation is applied to each bit
|
||||||
|
%%
|
||||||
|
%% NewBit = lxor(Bit,
|
||||||
|
%% land(lnot(BitToTheRight),
|
||||||
|
%% Bit2ToTheRight))
|
||||||
|
|
||||||
|
chi(Array1600) ->
|
||||||
|
chi(Array1600, 0).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-spec chi(Array1600, Idx0) -> NewArray1600
|
||||||
|
when Array1600 :: <<_:1600>>,
|
||||||
|
Idx0 :: non_neg_integer(),
|
||||||
|
NewArray1600 :: <<_:1600>>.
|
||||||
|
%% @private
|
||||||
|
%% The chi step. The following transformation is applied to each bit
|
||||||
|
%%
|
||||||
|
%% NewBit = lxor(Bit,
|
||||||
|
%% land(lnot(BitToTheRight),
|
||||||
|
%% Bit2ToTheRight))
|
||||||
|
%%
|
||||||
|
%% FIXME: Could be made more efficient by operating on lanes
|
||||||
|
|
||||||
|
chi(Array1600, ThisIdx0) when 0 =< ThisIdx0, ThisIdx0 =< 1599 ->
|
||||||
|
ThisXYZ = {xyz, ThisX , ThisY, ThisZ} = idx0_to_xyz(ThisIdx0),
|
||||||
|
RightXYZ = {xyz, right(ThisX) , ThisY, ThisZ},
|
||||||
|
Right2XYZ = {xyz, right(right(ThisX)), ThisY, ThisZ},
|
||||||
|
ThisBit = xyzth(ThisXYZ , Array1600),
|
||||||
|
RightBit = xyzth(RightXYZ , Array1600),
|
||||||
|
Right2Bit = xyzth(Right2XYZ, Array1600),
|
||||||
|
NewBit = lxor(ThisBit,
|
||||||
|
land(lnot(RightBit),
|
||||||
|
Right2Bit)),
|
||||||
|
NewArray1600 = xyzset(ThisXYZ, Array1600, NewBit),
|
||||||
|
NewIdx0 = ThisIdx0 + 1,
|
||||||
|
chi(NewArray1600, NewIdx0);
|
||||||
|
% terminal case
|
||||||
|
chi(Array1600, 1600) ->
|
||||||
|
Array1600.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -950,6 +995,25 @@ xyzth(XYZ, Array1600) ->
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-spec xyzset(XYZ, Array1600, NewBit) -> NewArray1600
|
||||||
|
when XYZ :: {xyz, X, Y, Z},
|
||||||
|
Array1600 :: <<_:1600>>,
|
||||||
|
NewBit :: 0 | 1,
|
||||||
|
NewArray1600 :: Array1600,
|
||||||
|
X :: 0..4,
|
||||||
|
Y :: 0..4,
|
||||||
|
Z :: 0..63.
|
||||||
|
%% @private
|
||||||
|
%% Replace the bit at {X, Y, Z} with the new bit
|
||||||
|
%% @end
|
||||||
|
|
||||||
|
xyzset(XYZ, Array1600, NewBit) ->
|
||||||
|
Idx0 = xyz_to_idx0(XYZ),
|
||||||
|
<<Pre:Idx0, _Bit:1, Post/bitstring>> = Array1600,
|
||||||
|
<<Pre:Idx0, NewBit:1, Post/bitstring>>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%% 1D SUBSET ACCESSORS
|
%% 1D SUBSET ACCESSORS
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
%% @doc
|
||||||
|
%% this module exists to check that the table on pp. 12 of
|
||||||
|
%% https://www.crypto-textbook.com/download/Understanding-Cryptography-Keccak.pdf
|
||||||
|
%% is correct
|
||||||
|
-module(rc).
|
||||||
|
|
||||||
|
-compile(export_all).
|
||||||
|
|
||||||
|
-spec little_rc(T) -> Bit
|
||||||
|
when T :: non_neg_integer(),
|
||||||
|
Bit :: 0 | 1.
|
||||||
|
%% copying from pp. 16 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
|
||||||
|
little_rc(T) when (T rem 255) =:= 0 ->
|
||||||
|
1;
|
||||||
|
little_rc(T) ->
|
||||||
|
R = <<(2#1000):4, (2#0000):4>>, %% could make this 8 but splitting into 4 is clearer
|
||||||
|
InitI = 1,
|
||||||
|
TMod255 = T rem 255,
|
||||||
|
NewR = little_rc(InitI, TMod255, R),
|
||||||
|
<<Result:1, _/bitstring>> = NewR,
|
||||||
|
Result.
|
||||||
|
|
||||||
|
-spec little_rc(I, MaxI, R) -> NewR
|
||||||
|
when I :: pos_integer(),
|
||||||
|
MaxI :: pos_integer(),
|
||||||
|
R :: <<_:8>>,
|
||||||
|
NewR :: <<_:8>>.
|
||||||
|
|
||||||
|
little_rc(I, MaxI, R) when I =< MaxI ->
|
||||||
|
R_ = <<0:1, R/bitstring>>,
|
||||||
|
% need R_[0], R_[4], R_[5], R_[6], and R_[8]
|
||||||
|
<<R_0:1, R_123:3, R_4:1, R_5:1, R_6:1, R_7:1, R_8:1>> = R_,
|
||||||
|
NewR_0 = R_0 bxor R_8,
|
||||||
|
NewR_4 = R_4 bxor R_8,
|
||||||
|
NewR_5 = R_5 bxor R_8,
|
||||||
|
NewR_6 = R_6 bxor R_8,
|
||||||
|
NewR = <<NewR_0 :1,
|
||||||
|
R_123:3,
|
||||||
|
NewR_4 :1,
|
||||||
|
NewR_5 :1,
|
||||||
|
NewR_6 :1,
|
||||||
|
R_7 :1>>,
|
||||||
|
NewI = I + 1,
|
||||||
|
little_rc(NewI, MaxI, NewR);
|
||||||
|
little_rc(I, MaxI, R) when I > MaxI ->
|
||||||
|
R.
|
||||||
|
|
||||||
|
|
||||||
|
% Table from pp. 12 of https://www.crypto-textbook.com/download/Understanding-Cryptography-Keccak.pdf
|
||||||
|
%
|
||||||
|
% RC[ 0] = 0x0000000000000001
|
||||||
|
% RC[ 1] = 0x0000000000008082
|
||||||
|
% RC[ 2] = 0x800000000000808A
|
||||||
|
% RC[ 3] = 0x8000000080008000
|
||||||
|
% RC[ 4] = 0x000000000000808B
|
||||||
|
% RC[ 5] = 0x0000000080000001
|
||||||
|
% RC[ 6] = 0x8000000080008081
|
||||||
|
% RC[ 7] = 0x8000000000008009
|
||||||
|
% RC[ 8] = 0x000000000000008A
|
||||||
|
% RC[ 9] = 0x0000000000000088
|
||||||
|
% RC[10] = 0x0000000080008009
|
||||||
|
% RC[11] = 0x000000008000000A
|
||||||
|
% RC[12] = 0x000000008000808B
|
||||||
|
% RC[13] = 0x800000000000008B
|
||||||
|
% RC[14] = 0x8000000000008089
|
||||||
|
% RC[15] = 0x8000000000008003
|
||||||
|
% RC[16] = 0x8000000000008002
|
||||||
|
% RC[17] = 0x8000000000000080
|
||||||
|
% RC[18] = 0x000000000000800A
|
||||||
|
% RC[19] = 0x800000008000000A
|
||||||
|
% RC[20] = 0x8000000080008081
|
||||||
|
% RC[21] = 0x8000000000008080
|
||||||
|
% RC[22] = 0x0000000080000001
|
||||||
|
% RC[23] = 0x8000000080008008
|
||||||
|
|
||||||
|
-spec big_rc(RoundIndex) -> BigRC
|
||||||
|
when RoundIndex :: 0..23,
|
||||||
|
BigRC :: <<_:64>>.
|
||||||
|
|
||||||
|
%% from pp. 16 of the NIST doc:
|
||||||
|
%% > 2. Let RC = 0w.
|
||||||
|
%% > 3. For j from 0 to l, let RC[2^j – 1] = rc(j + 7*ir).
|
||||||
|
%%
|
||||||
|
%% In this case, 0w = <<0:64>>, l = 6, ir ranges between 0..23
|
||||||
|
%%
|
||||||
|
%% > 2. Let RC = 0w.
|
||||||
|
%% > 3. For j from 0 to 6, let RC[2^j – 1] = rc(j + 7*ir).
|
||||||
|
|
||||||
|
big_rc(RoundIndex) ->
|
||||||
|
InitJ = 0,
|
||||||
|
InitBigRC = <<0:64>>,
|
||||||
|
big_rc(RoundIndex, InitJ, InitBigRC).
|
||||||
|
|
||||||
|
|
||||||
|
-spec big_rc(RoundIndex, J, BigRCAcc) -> BigRC
|
||||||
|
when RoundIndex :: 0..23,
|
||||||
|
J :: 0..6,
|
||||||
|
BigRCAcc :: BigRC,
|
||||||
|
BigRC :: <<_:64>>.
|
||||||
|
|
||||||
|
%% > 3. For j from 0 to 6, let RC[2^j – 1] = rc(j + 7ir).
|
||||||
|
big_rc(RoundIndex, J, BigRCAcc) when 0 =< J, J =< 6 ->
|
||||||
|
Idx0WeAreModifying = two_to_the(J) - 1,
|
||||||
|
NewBit = little_rc(J + 7*RoundIndex),
|
||||||
|
NumSkipBits = Idx0WeAreModifying,
|
||||||
|
<<Pre:NumSkipBits, _:1, Post/bitstring>> = BigRCAcc,
|
||||||
|
NewJ = J + 1,
|
||||||
|
NewBigRCAcc = <<Pre:NumSkipBits, NewBit:1, Post/bitstring>>,
|
||||||
|
big_rc(RoundIndex, NewJ, NewBigRCAcc);
|
||||||
|
big_rc(_RoundIndex, J, BigRCAcc) when J > 6 ->
|
||||||
|
BigRCAcc.
|
||||||
|
|
||||||
|
two_to_the(N) when 0 =< N ->
|
||||||
|
1 bsl N.
|
||||||
|
|
||||||
|
|
||||||
|
%% expected values
|
||||||
|
xrc( 0) -> <<( 16#0000000000000001 ):64>>;
|
||||||
|
xrc( 1) -> <<( 16#0000000000008082 ):64>>;
|
||||||
|
xrc( 2) -> <<( 16#800000000000808A ):64>>;
|
||||||
|
xrc( 3) -> <<( 16#8000000080008000 ):64>>;
|
||||||
|
xrc( 4) -> <<( 16#000000000000808B ):64>>;
|
||||||
|
xrc( 5) -> <<( 16#0000000080000001 ):64>>;
|
||||||
|
xrc( 6) -> <<( 16#8000000080008081 ):64>>;
|
||||||
|
xrc( 7) -> <<( 16#8000000000008009 ):64>>;
|
||||||
|
xrc( 8) -> <<( 16#000000000000008A ):64>>;
|
||||||
|
xrc( 9) -> <<( 16#0000000000000088 ):64>>;
|
||||||
|
xrc(10) -> <<( 16#0000000080008009 ):64>>;
|
||||||
|
xrc(11) -> <<( 16#000000008000000A ):64>>;
|
||||||
|
xrc(12) -> <<( 16#000000008000808B ):64>>;
|
||||||
|
xrc(13) -> <<( 16#800000000000008B ):64>>;
|
||||||
|
xrc(14) -> <<( 16#8000000000008089 ):64>>;
|
||||||
|
xrc(15) -> <<( 16#8000000000008003 ):64>>;
|
||||||
|
xrc(16) -> <<( 16#8000000000008002 ):64>>;
|
||||||
|
xrc(17) -> <<( 16#8000000000000080 ):64>>;
|
||||||
|
xrc(18) -> <<( 16#000000000000800A ):64>>;
|
||||||
|
xrc(19) -> <<( 16#800000008000000A ):64>>;
|
||||||
|
xrc(20) -> <<( 16#8000000080008081 ):64>>;
|
||||||
|
xrc(21) -> <<( 16#8000000000008080 ):64>>;
|
||||||
|
xrc(22) -> <<( 16#0000000080000001 ):64>>;
|
||||||
|
xrc(23) -> <<( 16#8000000080008008 ):64>>.
|
||||||
|
|
||||||
|
|
||||||
|
check() ->
|
||||||
|
CheckI =
|
||||||
|
fun(I) ->
|
||||||
|
io:format("I = ~p: ~p~n", [I, big_rc(I) =:= xrc(I)])
|
||||||
|
end,
|
||||||
|
lists:foreach(CheckI, lists:seq(0, 23)).
|
||||||
Reference in New Issue
Block a user