Roma standalone #512
@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
%% NOTE: When possible deps are referenced by Git ref to ensure consistency between builds.
|
%% NOTE: When possible deps are referenced by Git ref to ensure consistency between builds.
|
||||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git",
|
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git",
|
||||||
{ref,"99bf097"}}},
|
{ref,"99bf097"}}}
|
||||||
|
|
||||||
% waiting for https://github.com/jlouis/enacl/pull/40 to be merged
|
|
||||||
{enacl, {git, "https://github.com/aeternity/enacl.git",
|
|
||||||
{ref, "26180f4"}}}
|
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
[{<<"aebytecode">>,
|
[{<<"aebytecode">>,
|
||||||
{git,"https://github.com/aeternity/aebytecode.git",
|
{git,"https://github.com/aeternity/aebytecode.git",
|
||||||
{ref,"99bf097759dedbe7553f87a796bc7e1c7322e64b"}},
|
{ref,"99bf097759dedbe7553f87a796bc7e1c7322e64b"}},
|
||||||
0},
|
|
||||||
{<<"enacl">>,
|
|
||||||
{git,"https://github.com/aeternity/enacl.git",
|
|
||||||
{ref,"26180f42c0b3a450905d2efd8bc7fd5fd9cece75"}},
|
|
||||||
0}].
|
0}].
|
||||||
|
@ -136,7 +136,7 @@ function_type_hash(Name, ArgType, OutType) when is_binary(Name) ->
|
|||||||
, aeso_heap:to_binary(OutType)
|
, aeso_heap:to_binary(OutType)
|
||||||
]),
|
]),
|
||||||
%% Calculate a 256 bit digest BLAKE2b hash value of a binary
|
%% Calculate a 256 bit digest BLAKE2b hash value of a binary
|
||||||
{ok, Hash} = enacl:generichash(?HASH_SIZE, Bin),
|
{ok, Hash} = aeso_blake2:blake2b(?HASH_SIZE, Bin),
|
||||||
Hash.
|
Hash.
|
||||||
|
|
||||||
-spec arg_typerep_from_function(function_name(), type_info()) ->
|
-spec arg_typerep_from_function(function_name(), type_info()) ->
|
||||||
|
149
src/aeso_blake2.erl
Normal file
149
src/aeso_blake2.erl
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
%%%=============================================================================
|
||||||
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% BLAKE2b implementation in Erlang - for details see: https://blake2.net
|
||||||
|
%%% @end
|
||||||
|
%%%=============================================================================
|
||||||
|
|
||||||
|
-module(aeso_blake2).
|
||||||
|
|
||||||
|
-export([ blake2b/2
|
||||||
|
, blake2b/3
|
||||||
|
]).
|
||||||
|
|
||||||
|
-define(MAX_64BIT, 16#ffffffffffffffff).
|
||||||
|
|
||||||
|
-spec blake2b(HashLen :: integer(), Msg :: binary()) -> {ok, binary()}.
|
||||||
|
blake2b(HashLen, Msg) ->
|
||||||
|
blake2b(HashLen, Msg, <<>>).
|
||||||
|
|
||||||
|
-spec blake2b(HashLen :: integer(), Msg :: binary(), Key :: binary()) -> {ok, binary()}.
|
||||||
|
blake2b(HashLen, Msg0, Key) ->
|
||||||
|
%% If message should be keyed, prepend message with padded key.
|
||||||
|
Msg = <<(pad(128, Key))/binary, Msg0/binary>>,
|
||||||
|
|
||||||
|
%% Set up the initial state
|
||||||
|
Init = (16#01010000 + (byte_size(Key) bsl 8) + HashLen),
|
||||||
|
<<H0:64, H1_7/binary>> = blake_iv(),
|
||||||
|
H = <<(H0 bxor Init):64, H1_7/binary>>,
|
||||||
|
|
||||||
|
%% Perform the compression - message will be chopped into 128-byte chunks.
|
||||||
|
State = blake2b_compress(H, Msg, 0),
|
||||||
|
|
||||||
|
%% Just return the requested part of the hash
|
||||||
|
{ok, binary_part(to_little_endian(State), {0, HashLen})}.
|
||||||
|
|
||||||
|
blake2b_compress(H, <<Chunk:(128*8), Rest/binary>>, BCompr) when Rest /= <<>> ->
|
||||||
|
H1 = blake2b_compress(H, <<Chunk:(128*8)>>, BCompr + 128, false),
|
||||||
|
blake2b_compress(H1, Rest, BCompr + 128);
|
||||||
|
blake2b_compress(H, SmallChunk, BCompr) ->
|
||||||
|
Size = byte_size(SmallChunk),
|
||||||
|
FillSize = (128 - Size) * 8,
|
||||||
|
blake2b_compress(H, <<SmallChunk/binary, 0:FillSize>>, BCompr + Size, true).
|
||||||
|
|
||||||
|
blake2b_compress(H, Chunk0, BCompr, Last) ->
|
||||||
|
Chunk = to_big_endian(Chunk0),
|
||||||
|
<<V0_11:(12*64), V12:64, V13:64, V14:64, V15:64>> = <<H/binary, (blake_iv())/binary>>,
|
||||||
|
V12_ = V12 bxor (BCompr band ?MAX_64BIT),
|
||||||
|
V13_ = V13 bxor ((BCompr bsr 64) band ?MAX_64BIT),
|
||||||
|
V14_ = case Last of
|
||||||
|
false -> V14;
|
||||||
|
true -> V14 bxor ?MAX_64BIT
|
||||||
|
end,
|
||||||
|
V = <<V0_11:(12*64), V12_:64, V13_:64, V14_:64, V15:64>>,
|
||||||
|
|
||||||
|
<<VLow:(8*64), VHigh:(8*64)>> =
|
||||||
|
lists:foldl(fun(Round, Vx) -> blake2b_mix(Round, Chunk, Vx) end, V, lists:seq(0, 11)),
|
||||||
|
|
||||||
|
<<HInt:(8*64)>> = H,
|
||||||
|
<<((HInt bxor VLow) bxor VHigh):(8*64)>>.
|
||||||
|
|
||||||
|
blake2b_mix(Rnd, Chunk, V) ->
|
||||||
|
<<V0:64, V1:64, V2:64, V3:64, V4:64, V5:64, V6:64, V7:64, V8:64,
|
||||||
|
V9:64, V10:64, V11:64, V12:64, V13:64, V14:64, V15:64>> = V,
|
||||||
|
<<M0:64, M1:64, M2:64, M3:64, M4:64, M5:64, M6:64, M7:64, M8:64,
|
||||||
|
M9:64, M10:64, M11:64, M12:64, M13:64, M14:64, M15:64>> = Chunk,
|
||||||
|
Ms = {M0, M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15},
|
||||||
|
M = fun(Ix) -> element(Ix+1, Ms) end,
|
||||||
|
|
||||||
|
[S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15] = sigma(Rnd rem 10),
|
||||||
|
|
||||||
|
{Vx0, Vx4, Vx8, Vx12} = blake2b_mix(V0, V4, V8, V12, M(S0), M(S1)),
|
||||||
|
{Vx1, Vx5, Vx9, Vx13} = blake2b_mix(V1, V5, V9, V13, M(S2), M(S3)),
|
||||||
|
{Vx2, Vx6, Vx10, Vx14} = blake2b_mix(V2, V6, V10, V14, M(S4), M(S5)),
|
||||||
|
{Vx3, Vx7, Vx11, Vx15} = blake2b_mix(V3, V7, V11, V15, M(S6), M(S7)),
|
||||||
|
|
||||||
|
{Vy0, Vy5, Vy10, Vy15} = blake2b_mix(Vx0, Vx5, Vx10, Vx15, M(S8), M(S9)),
|
||||||
|
{Vy1, Vy6, Vy11, Vy12} = blake2b_mix(Vx1, Vx6, Vx11, Vx12, M(S10), M(S11)),
|
||||||
|
{Vy2, Vy7, Vy8, Vy13} = blake2b_mix(Vx2, Vx7, Vx8, Vx13, M(S12), M(S13)),
|
||||||
|
{Vy3, Vy4, Vy9, Vy14} = blake2b_mix(Vx3, Vx4, Vx9, Vx14, M(S14), M(S15)),
|
||||||
|
|
||||||
|
<<Vy0:64, Vy1:64, Vy2:64, Vy3:64, Vy4:64, Vy5:64, Vy6:64, Vy7:64, Vy8:64,
|
||||||
|
Vy9:64, Vy10:64, Vy11:64, Vy12:64, Vy13:64, Vy14:64, Vy15:64>>.
|
||||||
|
|
||||||
|
blake2b_mix(Va, Vb, Vc, Vd, X, Y) ->
|
||||||
|
Va1 = (Va + Vb + X) band ?MAX_64BIT,
|
||||||
|
Vd1 = rotr64(32, Vd bxor Va1),
|
||||||
|
|
||||||
|
Vc1 = (Vc + Vd1) band ?MAX_64BIT,
|
||||||
|
Vb1 = rotr64(24, Vb bxor Vc1),
|
||||||
|
|
||||||
|
Va2 = (Va1 + Vb1 + Y) band ?MAX_64BIT,
|
||||||
|
Vd2 = rotr64(16, Va2 bxor Vd1),
|
||||||
|
|
||||||
|
Vc2 = (Vc1 + Vd2) band ?MAX_64BIT,
|
||||||
|
Vb2 = rotr64(63, Vb1 bxor Vc2),
|
||||||
|
|
||||||
|
{Va2, Vb2, Vc2, Vd2}.
|
||||||
|
|
||||||
|
blake_iv() ->
|
||||||
|
IV0 = 16#6A09E667F3BCC908,
|
||||||
|
IV1 = 16#BB67AE8584CAA73B,
|
||||||
|
IV2 = 16#3C6EF372FE94F82B,
|
||||||
|
IV3 = 16#A54FF53A5F1D36F1,
|
||||||
|
IV4 = 16#510E527FADE682D1,
|
||||||
|
IV5 = 16#9B05688C2B3E6C1F,
|
||||||
|
IV6 = 16#1F83D9ABFB41BD6B,
|
||||||
|
IV7 = 16#5BE0CD19137E2179,
|
||||||
|
<<IV0:64, IV1:64, IV2:64, IV3:64, IV4:64, IV5:64, IV6:64, IV7:64>>.
|
||||||
|
|
||||||
|
sigma(N) ->
|
||||||
|
{_, Row} = lists:keyfind(N, 1, sigma()), Row.
|
||||||
|
|
||||||
|
sigma() ->
|
||||||
|
[{0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]},
|
||||||
|
{1, [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3]},
|
||||||
|
{2, [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4]},
|
||||||
|
{3, [ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8]},
|
||||||
|
{4, [ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13]},
|
||||||
|
{5, [ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9]},
|
||||||
|
{6, [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11]},
|
||||||
|
{7, [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10]},
|
||||||
|
{8, [ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5]},
|
||||||
|
{9, [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0]}].
|
||||||
|
|
||||||
|
rotr64(N, I64) ->
|
||||||
|
<<I64rot:64>> = rotr641(N, <<I64:64>>),
|
||||||
|
I64rot.
|
||||||
|
|
||||||
|
rotr641(16, <<X:(64-16), Y:16>>) -> <<Y:16, X:(64-16)>>;
|
||||||
|
rotr641(24, <<X:(64-24), Y:24>>) -> <<Y:24, X:(64-24)>>;
|
||||||
|
rotr641(32, <<X:(64-32), Y:32>>) -> <<Y:32, X:(64-32)>>;
|
||||||
|
rotr641(63, <<X:(64-63), Y:63>>) -> <<Y:63, X:(64-63)>>.
|
||||||
|
|
||||||
|
pad(N, Bin) ->
|
||||||
|
case (N - (byte_size(Bin) rem N)) rem N of
|
||||||
|
0 -> Bin;
|
||||||
|
Pad -> <<Bin/binary, 0:(Pad *8)>>
|
||||||
|
end.
|
||||||
|
|
||||||
|
to_big_endian(Bin) -> to_big_endian(Bin, <<>>).
|
||||||
|
to_big_endian(<<>>, Acc) -> Acc;
|
||||||
|
to_big_endian(<<UInt64:1/little-unsigned-integer-unit:64, Rest/binary>>, Acc) ->
|
||||||
|
to_big_endian(Rest, <<Acc/binary, UInt64:1/big-unsigned-integer-unit:64>>).
|
||||||
|
|
||||||
|
to_little_endian(Bin) -> to_little_endian(Bin, <<>>).
|
||||||
|
to_little_endian(<<>>, Acc) -> Acc;
|
||||||
|
to_little_endian(<<UInt64:1/big-unsigned-integer-unit:64, Rest/binary>>, Acc) ->
|
||||||
|
to_little_endian(Rest, <<Acc/binary, UInt64:1/little-unsigned-integer-unit:64>>).
|
||||||
|
|
73
test/aeso_blake2_tests.erl
Normal file
73
test/aeso_blake2_tests.erl
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
%%%=============================================================================
|
||||||
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% Unit tests for the aeso_blake2 module
|
||||||
|
%%%
|
||||||
|
%%% In addition the aeso_blake2 module was compared to the C reference
|
||||||
|
%%% implementation by writing a QuickCheck property.
|
||||||
|
%%% @end
|
||||||
|
%%%=============================================================================
|
||||||
|
-module(aeso_blake2_tests).
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
blake2b_test_() ->
|
||||||
|
{"Tests for BLAKE2b hash implementation",
|
||||||
|
[ fun() -> blake2b(Data) end || Data <- test_data_blake2b() ]}.
|
||||||
|
|
||||||
|
blake2b({Msg0, Key0, ExpectedOut0}) ->
|
||||||
|
Msg = mk_binary(Msg0),
|
||||||
|
Key = mk_binary(Key0),
|
||||||
|
ExpectedOut = mk_binary(ExpectedOut0),
|
||||||
|
Result = aeso_blake2:blake2b(byte_size(ExpectedOut), Msg, Key),
|
||||||
|
?assertEqual(Result, {ok, ExpectedOut}).
|
||||||
|
|
||||||
|
mk_binary(Bin) when is_binary(Bin) -> Bin;
|
||||||
|
mk_binary(HexStr) when is_list(HexStr) ->
|
||||||
|
<< << (erlang:list_to_integer([H], 16)):4 >> || H <- HexStr >>.
|
||||||
|
|
||||||
|
test_data_blake2b() ->
|
||||||
|
[ %% {Message, Key, ExpectedHash}
|
||||||
|
%% From Wikipedia
|
||||||
|
%% https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2
|
||||||
|
{<<>>,
|
||||||
|
<<>>,
|
||||||
|
"786A02F742015903C6C6FD852552D272912F4740E15847618A86E217F71F5419D25E1031AFEE585313896444934EB04B903A685B1448B755D56F701AFE9BE2CE"}
|
||||||
|
, {<<"The quick brown fox jumps over the lazy dog">>,
|
||||||
|
<<>>,
|
||||||
|
"A8ADD4BDDDFD93E4877D2746E62817B116364A1FA7BC148D95090BC7333B3673F82401CF7AA2E4CB1ECD90296E3F14CB5413F8ED77BE73045B13914CDCD6A918"}
|
||||||
|
|
||||||
|
%% From reference implementation testvectors
|
||||||
|
%% https://github.com/BLAKE2/BLAKE2/tree/master/testvectors
|
||||||
|
%%
|
||||||
|
%% Non-keyed
|
||||||
|
, {"00",
|
||||||
|
"",
|
||||||
|
"2FA3F686DF876995167E7C2E5D74C4C7B6E48F8068FE0E44208344D480F7904C36963E44115FE3EB2A3AC8694C28BCB4F5A0F3276F2E79487D8219057A506E4B"}
|
||||||
|
, {"0001",
|
||||||
|
"",
|
||||||
|
"1C08798DC641ABA9DEE435E22519A4729A09B2BFE0FF00EF2DCD8ED6F8A07D15EAF4AEE52BBF18AB5608A6190F70B90486C8A7D4873710B1115D3DEBBB4327B5"}
|
||||||
|
, {"00010203040506070809",
|
||||||
|
"",
|
||||||
|
"29102511D749DB3CC9B4E335FA1F5E8FACA8421D558F6A3F3321D50D044A248BA595CFC3EFD3D2ADC97334DA732413F5CBF4751C362BA1D53862AC1E8DABEEE8"}
|
||||||
|
|
||||||
|
%% Keyed
|
||||||
|
, {"",
|
||||||
|
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||||
|
"10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568"}
|
||||||
|
, {"00",
|
||||||
|
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||||
|
"961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd"}
|
||||||
|
, {"0001",
|
||||||
|
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||||
|
"da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965"}
|
||||||
|
, {"00010203040506070809",
|
||||||
|
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||||
|
"4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd"}
|
||||||
|
].
|
||||||
|
|
||||||
|
|
||||||
|
-endif.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user