diff --git a/Emakefile b/Emakefile new file mode 100644 index 0000000..68c7b67 --- /dev/null +++ b/Emakefile @@ -0,0 +1 @@ +{"src/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..696ea1e --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 SUZUKI Tetsuya + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 624e1d3..7e1e3e9 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,29 @@ erlang-sha3 =========== -[![Build Status](https://secure.travis-ci.org/szktty/erlang-sha3.png?branch=develop)](http://travis-ci.org/szktty/erlang-sha3) +This repository contains: +1. the original 64-bit SHA-3 NIF library (forked from https://github.com/szktty/erlang-sha3 ) +2. Complete native Erlang fallback functions for both the Keccak and SHA-3 variants of the underlying algorithm -SHA-3 for Erlang (64 bit only) +The native Erlang version of the function not only provides a more complete cross-platform implementation than either +the original Keccak C library and the current SHA-3 implementation that ships with the Erlang stdlib. +This is also by far the most readable and understandable implementation in any language currently. +If you are a student of the Keccack hashing algorithm, the code in this repository is extremely useful. + +Peter Harpending wrote the original implementation with readability in mind, +and Hans Svensson greatly improved the performance of the readable implementation. Licenses -------- -This program is distributed under Apache License 2.0. +This program is distributed under the Apache License 2.0. Keccak source files are distributed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication license. -Author +Authors ------ -SUZUKI Tetsuya - +Orginal NIF wrapper: SUZUKI Tetsuya +Native Erlang functions: Peter Harpending, Hans Svensson, Craig Everett diff --git a/src/sha3.app.src b/src/sha3.app.src index c6b906e..bead42e 100644 --- a/src/sha3.app.src +++ b/src/sha3.app.src @@ -1,7 +1,7 @@ {application, sha3, [ {description, ""}, - {vsn, "0.1.2"}, + {vsn, "0.1.3"}, {registered, []}, {applications, [ kernel, diff --git a/src/sha3.erl b/src/sha3.erl index a40ddce..1fda218 100644 --- a/src/sha3.erl +++ b/src/sha3.erl @@ -1,8 +1,20 @@ +%%% @doc +%%% 2023-02-14: Update - Craig Everett +%%% Adapting native Erlang Keccak implementation as a NIF fallback +%%% to increase portability. Native Keccak implementation provided +%%% courtesy of Peter Harpending and Hans Svensson. +%%% +%%% Kek repo: +%%% https://github.com/pharpend/kek +%%% +%%% Peter Harpending: https://github.com/pharpend https://git.qpq.swiss/pharpend +%%% Hans Svensson: https://github.com/hanssv https://git.qpq.swiss/hanssv +%%% Craig Everett: https://gitlab.com/zxq9 https://git.qpq.swiss/zxq9 + -module(sha3). +-vsn("0.1.5"). +-export([hash_init/1, hash_update/2, hash_final/1, hash/2, kek/2, kek/3, shake128/2, shake256/2]). --export([hash_init/1, hash_update/2, hash_final/1, hash/2]). - --export([hexhash/2]). -on_load(init/0). @@ -16,50 +28,586 @@ -export_type([bitlen/0, context/0, digest/0]). -define(nif_stub, nif_stub_error(?LINE)). + nif_stub_error(Line) -> - erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). + erlang:nif_error({nif_not_loaded, module, ?MODULE, line, Line}). + init() -> - PrivDir = case code:priv_dir(?MODULE) of - {error, bad_name} -> - EbinDir = filename:dirname(code:which(?MODULE)), - AppPath = filename:dirname(EbinDir), - filename:join(AppPath, "priv"); - Path -> - Path - end, - erlang:load_nif(filename:join(PrivDir, sha3_nif), 0). + PrivDir = + case code:priv_dir(?MODULE) of + {error, bad_name} -> + EbinDir = filename:dirname(code:which(?MODULE)), + AppPath = filename:dirname(EbinDir), + filename:join(AppPath, "priv"); + Path -> + Path + end, + case erlang:load_nif(filename:join(PrivDir, sha3_nif), 0) of + ok -> + logger:info("erlang-sha3 NIF loaded."); + {error, {Reason, Message}} -> + Format = + "erlang-sha3 NIF failed to load with ~tw: ~ts. " + "Falling back to Erlang implementation.", + logger:info(Format, [Reason, Message]) + end. + +-spec hash_init(bitlen()) -> context(). %% @doc Returns a new context for hash operation. %% Bit length of digest (`BitLen') must be one of 224, 256, 384 and 512. %% @see hash_update/2 --spec hash_init(bitlen()) -> context(). + hash_init(_BitLen) -> ?nif_stub. + +-spec hash_update(context(), binary()) -> context(). %% @doc Updates the digest by `Context' generated with `hash_init/1' %% using the given `Data' and returns a new updated context. %% `Data' can be any length. %% The returned context can e used `hash_update/2' or `hash_final/1'. %% @see hash_final/1 --spec hash_update(context(), binary()) -> context(). + hash_update(_Context, _Binary) -> ?nif_stub. + +-spec hash_final(context()) -> digest(). %% @doc Finalizes the hash operation with `Context' and %% returns a message digest. %% Length of the digest is determined by an argument of `hash_init/1'. --spec hash_final(context()) -> digest(). + hash_final(_Context) -> ?nif_stub. -%% @doc Computes a message digest from `Binary'. -%% Bit length of digest (`BitLen') must be one of 224, 256, 384 and 512. --spec hash(bitlen(), binary()) -> digest(). -hash(_BitLen, _Binary) -> - ?nif_stub. --spec hexhash(bitlen(), binary()) -> binary(). -hexhash(Bitlen, Binary) -> - Hash = hash(Bitlen, Binary), - list_to_binary(hex2bin:bin_to_hexstr(Hash)). +-spec hash(OutputBitLength, Message) -> Digest + when OutputBitLength :: pos_integer(), + Message :: bitstring(), + Digest :: bitstring(). +%% @doc +%% SHA-3 with an arbitrary output bit length. +%% +%% This means Keccak with Capacity = 2 * OutputBitLength. Additionally, SHA3 +%% concatenates the bits 01 onto the end of the input, before sending the +%% Message to keccak/3. +%% @end + +hash(224, Message) -> kek(224, Message); +hash(256, Message) -> kek(256, Message); +hash(384, Message) -> kek(382, Message); +hash(512, Message) -> kek(512, Message); +hash(_, _) -> error(badarg). + + +kek(Length, Message) -> + kek(Length, Message, keccak). + +kek(OutputBitLength, Message, keccak) -> + Capacity = 2 * OutputBitLength, + keccak(Capacity, Message, <<>>, OutputBitLength); +kek(OutputBitLength, Message, nist) -> + Capacity = 2 * OutputBitLength, + keccak(Capacity, Message, <<2#01:2>>, OutputBitLength). + + +-spec shake128(Message, OutputBitLength) -> Digest + when Message :: bitstring(), + OutputBitLength :: pos_integer(), + Digest :: bitstring(). +%% @doc +%% This is the SHAKE variable-length hash with Capacity 256 = 2*128 bits. +%% @end + +shake128(Message, OutputBitLength) -> + shake(128, Message, OutputBitLength). + + +-spec shake256(Message, OutputBitLength) -> Digest + when Message :: bitstring(), + OutputBitLength :: pos_integer(), + Digest :: bitstring(). +%% @doc +%% This is the SHAKE variable-length hash with Capacity 512 = 2*256 bits. +%% @end + +shake256(Message, OutputBitLength) -> + shake(256, Message, OutputBitLength). + + +-spec shake(ShakeNumber, Message, OutputBitLength) -> Digest + when ShakeNumber :: pos_integer(), + Message :: bitstring(), + OutputBitLength :: pos_integer(), + Digest :: bitstring(). +%% @doc +%% This is the SHAKE variable-length hash with Capacity 512 = 2*ShakeNumber bits. +%% +%% This concatenates the bitstring 1111 onto the end of the Message before +%% sending the message to keccak/4. +%% @end + +shake(ShakeNumber, Message, OutputBitLength) -> + Capacity = 2 * ShakeNumber, + keccak(Capacity, Message, <<2#1111:4>>, OutputBitLength). + + + +%%% OUTER KECCAK +%%% +%%% Keccak pads the input, absorbs it into the sponge, and squeezes the bits out +%%% of the sponge. The absorption and squeezing phases invoke "inner keccak", +%%% which is the heart of the algorithm. +%%% +%%% - keccak/3 +%%% - pad/2 +%%% - absorb/4 +%%% - squeeze/3 + + +-spec keccak(Capacity, Message, Delimiter, OutputBitLength) -> Digest + when Capacity :: pos_integer(), + Message :: bitstring(), + Delimiter :: 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, Message, Delimiter, OutputBitLength) -> + BitRate = 1600 - Capacity, + PaddedMessage = pad(Message, Delimiter, BitRate), + InitialSponge = <<0:1600>>, + WetSponge = absorb(PaddedMessage, BitRate, Capacity, InitialSponge), + ResultBits = squeeze(WetSponge, OutputBitLength, BitRate), + ResultBits. + + +-spec pad(Message, Delimiter, BitRate) -> NewMessage + when Message :: bitstring(), + Delimiter :: 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 + +pad(Msg, Delimiter, BitRate) -> + MsgBits = bit_size(Msg), + DlmBits = bit_size(Delimiter), + <> = Msg, + case (MsgBits + DlmBits) rem BitRate of + 0 -> %% We add a complete RWord + flip the last chunk of the message + <>; + N when N == BitRate - 1 -> %% Slightly retarded case + <>; + N -> + <> + end. + +%% Instead of reverting message bits, work with a "reversed" padding +rev_pad(Msg, Delimiter, PadZeros) -> + Pad = <>, + << (flip_bits(X)) || <> <= Pad >>. + +flip_bits(0) -> <<0:8>>; +flip_bits(<>) -> + <>; +flip_bits(N) -> flip_bits(<>). + +-spec absorb(PaddedMessage, BitRate, Capacity, SpongeAcc) -> WetSponge + when PaddedMessage :: bitstring(), + BitRate :: pos_integer(), + Capacity :: pos_integer(), + SpongeAcc :: <<_:1600>>, + WetSponge :: <<_:1600>>. +%% @private +%% Assumptions: +%% 1. BitRate + Capacity = 1600, +%% 2. BitRate divides the PaddedMessage length (i.e. already have done padding) +%% @end + +% can pull off r bits from the start of the message +absorb(PaddedMessageBits, BitRate = _r, Capacity = _c, Sponge) when BitRate =< bit_size(PaddedMessageBits) -> + <> = PaddedMessageBits, + % we bitwise xor the sponge against the r word followed by a bunch of 0s + <> = Sponge, + <> = <>, + FInputInt = SpongeInt bxor Foo, + FInputBits = <>, + NewSponge = inner_keccak(FInputBits), + absorb(Rest, BitRate, Capacity, NewSponge); +% empty string, return the sponge +absorb(<<>>, _r, _c, FinalSponge) -> + FinalSponge. + + +-spec squeeze(WetSponge, OutputBitLength, BitRate) -> ResultBits + when WetSponge :: <<_:1600>>, + OutputBitLength :: pos_integer(), + BitRate :: pos_integer(), + ResultBits :: bitstring(). +%% @private +%% squeeze the output bits out of the sponge +%% @end + +%%% % simple case: bit length is less than (or equal to) the sponge size, just grab +%%% % the first ones +%%% % this is the case for the shas +%%% squeeze(<>, OutputBitLength, _BitRate) -> +%%% <>; +% general case: output bit length is greater than the sponge size, construct +% accumulatively +% this is the case for the variable-length encodings +squeeze(WetSponge, OutputBitLength, BitRate) -> + InitOutputAcc = <<>>, + really_squeeze(WetSponge, OutputBitLength, BitRate, InitOutputAcc). + +% terminal case: we have enough bits in the output, return those +really_squeeze(_WetSponge, OutputBitLength, _BitRate, FinalAccBits) when OutputBitLength =< bit_size(FinalAccBits) -> + <> = FinalAccBits, + <>; +% general case: need moar bits +% in this case +% - we grab the first r bits of the sponge, add them to the accumulator +% - re-kek the sponge +% - try again +really_squeeze(WetSponge, OutputBitLength, BitRate, ResultAcc)-> + <> = WetSponge, + NewResultAcc = <>, + NewWetSponge = inner_keccak(WetSponge), + really_squeeze(NewWetSponge, OutputBitLength, BitRate, NewResultAcc). + + +%%% THE DREADED INNER KECCAK +%%% +%%% This is the "f" function that appears in all the documentation. +%%% +%%% The input is the 1600-bit sponge array. inner_keccak/1 sends the input +%%% through 24 "rounds". Each round consists of the 5 Greek letter steps, each of +%%% which is a weird transformation on the array. +%%% +%%% Here the rounds are unrolled in terms of 64bit integers - for efficiency + + +inner_keccak(<<_:1600>> = State) -> + IntState0 = list_to_tuple([ X || <> <= State ]), + IntState6 = inner_keccak_fast(IntState0), + << <> || X <- tuple_to_list(IntState6) >>. + +inner_keccak_fast(IntState0) -> + IntState1 = fast_round(IntState0, {16#0000000000000001, 16#0000000000008082, 16#800000000000808A, 16#8000000080008000}), + IntState2 = fast_round(IntState1, {16#000000000000808B, 16#0000000080000001, 16#8000000080008081, 16#8000000000008009}), + IntState3 = fast_round(IntState2, {16#000000000000008A, 16#0000000000000088, 16#0000000080008009, 16#000000008000000A}), + IntState4 = fast_round(IntState3, {16#000000008000808B, 16#800000000000008B, 16#8000000000008089, 16#8000000000008003}), + IntState5 = fast_round(IntState4, {16#8000000000008002, 16#8000000000000080, 16#000000000000800A, 16#800000008000000A}), + fast_round(IntState5, {16#8000000080008081, 16#8000000000008080, 16#0000000080000001, 16#8000000080008008}). + +-define(INT64, 16#FFFFFFFFFFFFFFFF). +-define(BSL64(X, N), ((X bsl N) band ?INT64)). +-define(BSR64(X, N), (X bsr N)). + +-define(ROTL64(X, N), (?BSL64(X, N) bor ?BSR64(X, (64 - N)))). +-define(CAN64(A, B), ((A bxor B) band A)). + +fast_round(As0, {RC0, RC1, RC2, RC3}) -> + As1 = fast_round1(As0, RC0), + As2 = fast_round2(As1, RC1), + As3 = fast_round3(As2, RC2), + fast_round4(As3, RC3). + +fast_round1({A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24}, RC0) -> + %% Round 1 + BC0_0 = A0 bxor A5 bxor A10 bxor A15 bxor A20, + BC1_0 = A1 bxor A6 bxor A11 bxor A16 bxor A21, + BC2_0 = A2 bxor A7 bxor A12 bxor A17 bxor A22, + BC3_0 = A3 bxor A8 bxor A13 bxor A18 bxor A23, + BC4_0 = A4 bxor A9 bxor A14 bxor A19 bxor A24, + D0 = BC4_0 bxor ?ROTL64(BC1_0, 1), + D1 = BC0_0 bxor ?ROTL64(BC2_0, 1), + D2 = BC1_0 bxor ?ROTL64(BC3_0, 1), + D3 = BC2_0 bxor ?ROTL64(BC4_0, 1), + D4 = BC3_0 bxor ?ROTL64(BC0_0, 1), + + BC0_1 = A0 bxor D0, + BC1_1 = ?ROTL64(A6 bxor D1, 44), + BC2_1 = ?ROTL64(A12 bxor D2, 43), + BC3_1 = ?ROTL64(A18 bxor D3, 21), + BC4_1 = ?ROTL64(A24 bxor D4, 14), + A0_1 = BC0_1 bxor ?CAN64(BC2_1, BC1_1) bxor RC0, + A6_1 = BC1_1 bxor ?CAN64(BC3_1, BC2_1), + A12_1 = BC2_1 bxor ?CAN64(BC4_1, BC3_1), + A18_1 = BC3_1 bxor ?CAN64(BC0_1, BC4_1), + A24_1 = BC4_1 bxor ?CAN64(BC1_1, BC0_1), + + BC2_2 = ?ROTL64(A10 bxor D0, 3), + BC3_2 = ?ROTL64(A16 bxor D1, 45), + BC4_2 = ?ROTL64(A22 bxor D2, 61), + BC0_2 = ?ROTL64(A3 bxor D3, 28), + BC1_2 = ?ROTL64(A9 bxor D4, 20), + A10_1 = BC0_2 bxor ?CAN64(BC2_2, BC1_2), + A16_1 = BC1_2 bxor ?CAN64(BC3_2, BC2_2), + A22_1 = BC2_2 bxor ?CAN64(BC4_2, BC3_2), + A3_1 = BC3_2 bxor ?CAN64(BC0_2, BC4_2), + A9_1 = BC4_2 bxor ?CAN64(BC1_2, BC0_2), + + BC4_3 = ?ROTL64(A20 bxor D0, 18), + BC0_3 = ?ROTL64(A1 bxor D1, 1), + BC1_3 = ?ROTL64(A7 bxor D2, 6), + BC2_3 = ?ROTL64(A13 bxor D3, 25), + BC3_3 = ?ROTL64(A19 bxor D4, 8), + A20_1 = BC0_3 bxor ?CAN64(BC2_3, BC1_3), + A1_1 = BC1_3 bxor ?CAN64(BC3_3, BC2_3), + A7_1 = BC2_3 bxor ?CAN64(BC4_3, BC3_3), + A13_1 = BC3_3 bxor ?CAN64(BC0_3, BC4_3), + A19_1 = BC4_3 bxor ?CAN64(BC1_3, BC0_3), + + BC1_4 = ?ROTL64(A5 bxor D0, 36), + BC2_4 = ?ROTL64(A11 bxor D1, 10), + BC3_4 = ?ROTL64(A17 bxor D2, 15), + BC4_4 = ?ROTL64(A23 bxor D3, 56), + BC0_4 = ?ROTL64(A4 bxor D4, 27), + A5_1 = BC0_4 bxor ?CAN64(BC2_4, BC1_4), + A11_1 = BC1_4 bxor ?CAN64(BC3_4, BC2_4), + A17_1 = BC2_4 bxor ?CAN64(BC4_4, BC3_4), + A23_1 = BC3_4 bxor ?CAN64(BC0_4, BC4_4), + A4_1 = BC4_4 bxor ?CAN64(BC1_4, BC0_4), + + BC3_5 = ?ROTL64(A15 bxor D0, 41), + BC4_5 = ?ROTL64(A21 bxor D1, 2), + BC0_5 = ?ROTL64(A2 bxor D2, 62), + BC1_5 = ?ROTL64(A8 bxor D3, 55), + BC2_5 = ?ROTL64(A14 bxor D4, 39), + A15_1 = BC0_5 bxor ?CAN64(BC2_5, BC1_5), + A21_1 = BC1_5 bxor ?CAN64(BC3_5, BC2_5), + A2_1 = BC2_5 bxor ?CAN64(BC4_5, BC3_5), + A8_1 = BC3_5 bxor ?CAN64(BC0_5, BC4_5), + A14_1 = BC4_5 bxor ?CAN64(BC1_5, BC0_5), + + {A0_1, A1_1, A2_1, A3_1, A4_1, A5_1, A6_1, A7_1, A8_1, A9_1, A10_1, A11_1, A12_1, A13_1, + A14_1, A15_1, A16_1, A17_1, A18_1, A19_1, A20_1, A21_1, A22_1, A23_1, A24_1}. + +fast_round2({A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24}, RC1) -> + %% Round 2 + BC0_0 = A0 bxor A5 bxor A10 bxor A15 bxor A20, + BC1_0 = A1 bxor A6 bxor A11 bxor A16 bxor A21, + BC2_0 = A2 bxor A7 bxor A12 bxor A17 bxor A22, + BC3_0 = A3 bxor A8 bxor A13 bxor A18 bxor A23, + BC4_0 = A4 bxor A9 bxor A14 bxor A19 bxor A24, + D0 = BC4_0 bxor ?ROTL64(BC1_0, 1), + D1 = BC0_0 bxor ?ROTL64(BC2_0, 1), + D2 = BC1_0 bxor ?ROTL64(BC3_0, 1), + D3 = BC2_0 bxor ?ROTL64(BC4_0, 1), + D4 = BC3_0 bxor ?ROTL64(BC0_0, 1), + + BC0_1 = A0 bxor D0, + BC1_1 = ?ROTL64(A16 bxor D1, 44), + BC2_1 = ?ROTL64(A7 bxor D2, 43), + BC3_1 = ?ROTL64(A23 bxor D3, 21), + BC4_1 = ?ROTL64(A14 bxor D4, 14), + A0_1 = BC0_1 bxor ?CAN64(BC2_1, BC1_1) bxor RC1, + A16_1 = BC1_1 bxor ?CAN64(BC3_1, BC2_1), + A7_1 = BC2_1 bxor ?CAN64(BC4_1, BC3_1), + A23_1 = BC3_1 bxor ?CAN64(BC0_1, BC4_1), + A14_1 = BC4_1 bxor ?CAN64(BC1_1, BC0_1), + + BC2_2 = ?ROTL64(A20 bxor D0, 3), + BC3_2 = ?ROTL64(A11 bxor D1, 45), + BC4_2 = ?ROTL64(A2 bxor D2, 61), + BC0_2 = ?ROTL64(A18 bxor D3, 28), + BC1_2 = ?ROTL64(A9 bxor D4, 20), + A20_1 = BC0_2 bxor ?CAN64(BC2_2, BC1_2), + A11_1 = BC1_2 bxor ?CAN64(BC3_2, BC2_2), + A2_1 = BC2_2 bxor ?CAN64(BC4_2, BC3_2), + A18_1 = BC3_2 bxor ?CAN64(BC0_2, BC4_2), + A9_1 = BC4_2 bxor ?CAN64(BC1_2, BC0_2), + + BC4_3 = ?ROTL64(A15 bxor D0, 18), + BC0_3 = ?ROTL64(A6 bxor D1, 1), + BC1_3 = ?ROTL64(A22 bxor D2, 6), + BC2_3 = ?ROTL64(A13 bxor D3, 25), + BC3_3 = ?ROTL64(A4 bxor D4, 8), + A15_1 = BC0_3 bxor ?CAN64(BC2_3, BC1_3), + A6_1 = BC1_3 bxor ?CAN64(BC3_3, BC2_3), + A22_1 = BC2_3 bxor ?CAN64(BC4_3, BC3_3), + A13_1 = BC3_3 bxor ?CAN64(BC0_3, BC4_3), + A4_1 = BC4_3 bxor ?CAN64(BC1_3, BC0_3), + + BC1_4 = ?ROTL64(A10 bxor D0, 36), + BC2_4 = ?ROTL64(A1 bxor D1, 10), + BC3_4 = ?ROTL64(A17 bxor D2, 15), + BC4_4 = ?ROTL64(A8 bxor D3, 56), + BC0_4 = ?ROTL64(A24 bxor D4, 27), + A10_1 = BC0_4 bxor ?CAN64(BC2_4, BC1_4), + A1_1 = BC1_4 bxor ?CAN64(BC3_4, BC2_4), + A17_1 = BC2_4 bxor ?CAN64(BC4_4, BC3_4), + A8_1 = BC3_4 bxor ?CAN64(BC0_4, BC4_4), + A24_1 = BC4_4 bxor ?CAN64(BC1_4, BC0_4), + + BC3_5 = ?ROTL64(A5 bxor D0, 41), + BC4_5 = ?ROTL64(A21 bxor D1, 2), + BC0_5 = ?ROTL64(A12 bxor D2, 62), + BC1_5 = ?ROTL64(A3 bxor D3, 55), + BC2_5 = ?ROTL64(A19 bxor D4, 39), + A5_1 = BC0_5 bxor ?CAN64(BC2_5, BC1_5), + A21_1 = BC1_5 bxor ?CAN64(BC3_5, BC2_5), + A12_1 = BC2_5 bxor ?CAN64(BC4_5, BC3_5), + A3_1 = BC3_5 bxor ?CAN64(BC0_5, BC4_5), + A19_1 = BC4_5 bxor ?CAN64(BC1_5, BC0_5), + + {A0_1, A1_1, A2_1, A3_1, A4_1, A5_1, A6_1, A7_1, A8_1, A9_1, A10_1, A11_1, A12_1, A13_1, + A14_1, A15_1, A16_1, A17_1, A18_1, A19_1, A20_1, A21_1, A22_1, A23_1, A24_1}. + +fast_round3({A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24}, RC2) -> + %% Round 3 + BC0_0 = A0 bxor A5 bxor A10 bxor A15 bxor A20, + BC1_0 = A1 bxor A6 bxor A11 bxor A16 bxor A21, + BC2_0 = A2 bxor A7 bxor A12 bxor A17 bxor A22, + BC3_0 = A3 bxor A8 bxor A13 bxor A18 bxor A23, + BC4_0 = A4 bxor A9 bxor A14 bxor A19 bxor A24, + D0 = BC4_0 bxor ?ROTL64(BC1_0, 1), + D1 = BC0_0 bxor ?ROTL64(BC2_0, 1), + D2 = BC1_0 bxor ?ROTL64(BC3_0, 1), + D3 = BC2_0 bxor ?ROTL64(BC4_0, 1), + D4 = BC3_0 bxor ?ROTL64(BC0_0, 1), + + BC0_1 = A0 bxor D0, + BC1_1 = ?ROTL64(A11 bxor D1, 44), + BC2_1 = ?ROTL64(A22 bxor D2, 43), + BC3_1 = ?ROTL64(A8 bxor D3, 21), + BC4_1 = ?ROTL64(A19 bxor D4, 14), + A0_1 = BC0_1 bxor ?CAN64(BC2_1, BC1_1) bxor RC2, + A11_1 = BC1_1 bxor ?CAN64(BC3_1, BC2_1), + A22_1 = BC2_1 bxor ?CAN64(BC4_1, BC3_1), + A8_1 = BC3_1 bxor ?CAN64(BC0_1, BC4_1), + A19_1 = BC4_1 bxor ?CAN64(BC1_1, BC0_1), + + BC2_2 = ?ROTL64(A15 bxor D0, 3), + BC3_2 = ?ROTL64(A1 bxor D1, 45), + BC4_2 = ?ROTL64(A12 bxor D2, 61), + BC0_2 = ?ROTL64(A23 bxor D3, 28), + BC1_2 = ?ROTL64(A9 bxor D4, 20), + A15_1 = BC0_2 bxor ?CAN64(BC2_2, BC1_2), + A1_1 = BC1_2 bxor ?CAN64(BC3_2, BC2_2), + A12_1 = BC2_2 bxor ?CAN64(BC4_2, BC3_2), + A23_1 = BC3_2 bxor ?CAN64(BC0_2, BC4_2), + A9_1 = BC4_2 bxor ?CAN64(BC1_2, BC0_2), + + BC4_3 = ?ROTL64(A5 bxor D0, 18), + BC0_3 = ?ROTL64(A16 bxor D1, 1), + BC1_3 = ?ROTL64(A2 bxor D2, 6), + BC2_3 = ?ROTL64(A13 bxor D3, 25), + BC3_3 = ?ROTL64(A24 bxor D4, 8), + A5_1 = BC0_3 bxor ?CAN64(BC2_3, BC1_3), + A16_1 = BC1_3 bxor ?CAN64(BC3_3, BC2_3), + A2_1 = BC2_3 bxor ?CAN64(BC4_3, BC3_3), + A13_1 = BC3_3 bxor ?CAN64(BC0_3, BC4_3), + A24_1 = BC4_3 bxor ?CAN64(BC1_3, BC0_3), + + BC1_4 = ?ROTL64(A20 bxor D0, 36), + BC2_4 = ?ROTL64(A6 bxor D1, 10), + BC3_4 = ?ROTL64(A17 bxor D2, 15), + BC4_4 = ?ROTL64(A3 bxor D3, 56), + BC0_4 = ?ROTL64(A14 bxor D4, 27), + A20_1 = BC0_4 bxor ?CAN64(BC2_4, BC1_4), + A6_1 = BC1_4 bxor ?CAN64(BC3_4, BC2_4), + A17_1 = BC2_4 bxor ?CAN64(BC4_4, BC3_4), + A3_1 = BC3_4 bxor ?CAN64(BC0_4, BC4_4), + A14_1 = BC4_4 bxor ?CAN64(BC1_4, BC0_4), + + BC3_5 = ?ROTL64(A10 bxor D0, 41), + BC4_5 = ?ROTL64(A21 bxor D1, 2), + BC0_5 = ?ROTL64(A7 bxor D2, 62), + BC1_5 = ?ROTL64(A18 bxor D3, 55), + BC2_5 = ?ROTL64(A4 bxor D4, 39), + A10_1 = BC0_5 bxor ?CAN64(BC2_5, BC1_5), + A21_1 = BC1_5 bxor ?CAN64(BC3_5, BC2_5), + A7_1 = BC2_5 bxor ?CAN64(BC4_5, BC3_5), + A18_1 = BC3_5 bxor ?CAN64(BC0_5, BC4_5), + A4_1 = BC4_5 bxor ?CAN64(BC1_5, BC0_5), + + {A0_1, A1_1, A2_1, A3_1, A4_1, A5_1, A6_1, A7_1, A8_1, A9_1, A10_1, A11_1, A12_1, A13_1, + A14_1, A15_1, A16_1, A17_1, A18_1, A19_1, A20_1, A21_1, A22_1, A23_1, A24_1}. + +fast_round4({A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24}, RC3) -> + %% Round 4 + BC0_0 = A0 bxor A5 bxor A10 bxor A15 bxor A20, + BC1_0 = A1 bxor A6 bxor A11 bxor A16 bxor A21, + BC2_0 = A2 bxor A7 bxor A12 bxor A17 bxor A22, + BC3_0 = A3 bxor A8 bxor A13 bxor A18 bxor A23, + BC4_0 = A4 bxor A9 bxor A14 bxor A19 bxor A24, + D0 = BC4_0 bxor ?ROTL64(BC1_0, 1), + D1 = BC0_0 bxor ?ROTL64(BC2_0, 1), + D2 = BC1_0 bxor ?ROTL64(BC3_0, 1), + D3 = BC2_0 bxor ?ROTL64(BC4_0, 1), + D4 = BC3_0 bxor ?ROTL64(BC0_0, 1), + + BC0_1 = A0 bxor D0, + BC1_1 = ?ROTL64(A1 bxor D1, 44), + BC2_1 = ?ROTL64(A2 bxor D2, 43), + BC3_1 = ?ROTL64(A3 bxor D3, 21), + BC4_1 = ?ROTL64(A4 bxor D4, 14), + A0_1 = BC0_1 bxor ?CAN64(BC2_1, BC1_1) bxor RC3, + A1_1 = BC1_1 bxor ?CAN64(BC3_1, BC2_1), + A2_1 = BC2_1 bxor ?CAN64(BC4_1, BC3_1), + A3_1 = BC3_1 bxor ?CAN64(BC0_1, BC4_1), + A4_1 = BC4_1 bxor ?CAN64(BC1_1, BC0_1), + + BC2_2 = ?ROTL64(A5 bxor D0, 3), + BC3_2 = ?ROTL64(A6 bxor D1, 45), + BC4_2 = ?ROTL64(A7 bxor D2, 61), + BC0_2 = ?ROTL64(A8 bxor D3, 28), + BC1_2 = ?ROTL64(A9 bxor D4, 20), + A5_1 = BC0_2 bxor ?CAN64(BC2_2, BC1_2), + A6_1 = BC1_2 bxor ?CAN64(BC3_2, BC2_2), + A7_1 = BC2_2 bxor ?CAN64(BC4_2, BC3_2), + A8_1 = BC3_2 bxor ?CAN64(BC0_2, BC4_2), + A9_1 = BC4_2 bxor ?CAN64(BC1_2, BC0_2), + + BC4_3 = ?ROTL64(A10 bxor D0, 18), + BC0_3 = ?ROTL64(A11 bxor D1, 1), + BC1_3 = ?ROTL64(A12 bxor D2, 6), + BC2_3 = ?ROTL64(A13 bxor D3, 25), + BC3_3 = ?ROTL64(A14 bxor D4, 8), + A10_1 = BC0_3 bxor ?CAN64(BC2_3, BC1_3), + A11_1 = BC1_3 bxor ?CAN64(BC3_3, BC2_3), + A12_1 = BC2_3 bxor ?CAN64(BC4_3, BC3_3), + A13_1 = BC3_3 bxor ?CAN64(BC0_3, BC4_3), + A14_1 = BC4_3 bxor ?CAN64(BC1_3, BC0_3), + + BC1_4 = ?ROTL64(A15 bxor D0, 36), + BC2_4 = ?ROTL64(A16 bxor D1, 10), + BC3_4 = ?ROTL64(A17 bxor D2, 15), + BC4_4 = ?ROTL64(A18 bxor D3, 56), + BC0_4 = ?ROTL64(A19 bxor D4, 27), + A15_1 = BC0_4 bxor ?CAN64(BC2_4, BC1_4), + A16_1 = BC1_4 bxor ?CAN64(BC3_4, BC2_4), + A17_1 = BC2_4 bxor ?CAN64(BC4_4, BC3_4), + A18_1 = BC3_4 bxor ?CAN64(BC0_4, BC4_4), + A19_1 = BC4_4 bxor ?CAN64(BC1_4, BC0_4), + + BC3_5 = ?ROTL64(A20 bxor D0, 41), + BC4_5 = ?ROTL64(A21 bxor D1, 2), + BC0_5 = ?ROTL64(A22 bxor D2, 62), + BC1_5 = ?ROTL64(A23 bxor D3, 55), + BC2_5 = ?ROTL64(A24 bxor D4, 39), + A20_1 = BC0_5 bxor ?CAN64(BC2_5, BC1_5), + A21_1 = BC1_5 bxor ?CAN64(BC3_5, BC2_5), + A22_1 = BC2_5 bxor ?CAN64(BC4_5, BC3_5), + A23_1 = BC3_5 bxor ?CAN64(BC0_5, BC4_5), + A24_1 = BC4_5 bxor ?CAN64(BC1_5, BC0_5), + + {A0_1, A1_1, A2_1, A3_1, A4_1, A5_1, A6_1, A7_1, A8_1, A9_1, A10_1, A11_1, A12_1, A13_1, + A14_1, A15_1, A16_1, A17_1, A18_1, A19_1, A20_1, A21_1, A22_1, A23_1, A24_1}. diff --git a/src/sha3.py b/src/sha3.py new file mode 100644 index 0000000..0b9608f --- /dev/null +++ b/src/sha3.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Implementation by Gilles Van Assche, hereby denoted as "the implementer". +# +# For more information, feedback or questions, please refer to our website: +# https://keccak.team/ +# +# To the extent possible under law, the implementer has waived all copyright +# and related or neighboring rights to the source code in this file. +# http://creativecommons.org/publicdomain/zero/1.0/ + +def ROL64(a, n): + return ((a >> (64-(n%64))) + (a << (n%64))) % (1 << 64) + +def KeccakF1600onLanes(lanes): + R = 1 + for round in range(24): + # θ + C = [lanes[x][0] ^ lanes[x][1] ^ lanes[x][2] ^ lanes[x][3] ^ lanes[x][4] for x in range(5)] + D = [C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1) for x in range(5)] + lanes = [[lanes[x][y]^D[x] for y in range(5)] for x in range(5)] + # ρ and π + (x, y) = (1, 0) + current = lanes[x][y] + for t in range(24): + (x, y) = (y, (2*x+3*y)%5) + (current, lanes[x][y]) = (lanes[x][y], ROL64(current, (t+1)*(t+2)//2)) + # χ + for y in range(5): + T = [lanes[x][y] for x in range(5)] + for x in range(5): + lanes[x][y] = T[x] ^((~T[(x+1)%5]) & T[(x+2)%5]) + # ι + for j in range(7): + R = ((R << 1) ^ ((R >> 7)*0x71)) % 256 + if (R & 2): + lanes[0][0] = lanes[0][0] ^ (1 << ((1<> (8*i)) % 256 for i in range(8)) + +def KeccakF1600(state): + lanes = [[load64(state[8*(x+5*y):8*(x+5*y)+8]) for y in range(5)] for x in range(5)] + lanes = KeccakF1600onLanes(lanes) + state = bytearray(200) + for x in range(5): + for y in range(5): + state[8*(x+5*y):8*(x+5*y)+8] = store64(lanes[x][y]) + return state + +def Keccak(rate, capacity, inputBytes, delimitedSuffix, outputByteLen): + outputBytes = bytearray() + state = bytearray([0 for i in range(200)]) + rateInBytes = rate//8 + blockSize = 0 + if (((rate + capacity) != 1600) or ((rate % 8) != 0)): + return + inputOffset = 0 + # === Absorb all the input blocks === + while(inputOffset < len(inputBytes)): + blockSize = min(len(inputBytes)-inputOffset, rateInBytes) + for i in range(blockSize): + state[i] = state[i] ^ inputBytes[i+inputOffset] + inputOffset = inputOffset + blockSize + if (blockSize == rateInBytes): + state = KeccakF1600(state) + blockSize = 0 + # === Do the padding and switch to the squeezing phase === + state[blockSize] = state[blockSize] ^ delimitedSuffix + if (((delimitedSuffix & 0x80) != 0) and (blockSize == (rateInBytes-1))): + state = KeccakF1600(state) + state[rateInBytes-1] = state[rateInBytes-1] ^ 0x80 + state = KeccakF1600(state) + # === Squeeze out all the output blocks === + while(outputByteLen > 0): + blockSize = min(outputByteLen, rateInBytes) + outputBytes = outputBytes + state[0:blockSize] + outputByteLen = outputByteLen - blockSize + if (outputByteLen > 0): + state = KeccakF1600(state) + return outputBytes + +def SHAKE128(inputBytes, outputByteLen): + return Keccak(1344, 256, inputBytes, 0x1F, outputByteLen) + +def SHAKE256(inputBytes, outputByteLen): + return Keccak(1088, 512, inputBytes, 0x1F, outputByteLen) + +def SHA3_224(inputBytes): + return Keccak(1152, 448, inputBytes, 0x06, 224//8) + +def SHA3_256(inputBytes): + return Keccak(1088, 512, inputBytes, 0x06, 256//8) + +def SHA3_384(inputBytes): + return Keccak(832, 768, inputBytes, 0x06, 384//8) + +def SHA3_512(inputBytes): + return Keccak(576, 1024, inputBytes, 0x06, 512//8) diff --git a/test/sha3_tests.erl b/test/sha3_tests.erl index 893b69d..22da997 100644 --- a/test/sha3_tests.erl +++ b/test/sha3_tests.erl @@ -34,31 +34,30 @@ hash_224_test() -> ?assertEqual(<<16#038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1:224>>, sha3:hash(224, <<16#00112233445566778899AABBCCDDEEFF:128>>)). +hash_224_native_test() -> + ?assertEqual(<<16#038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1:224>>, + sha3:kek(224, <<16#00112233445566778899AABBCCDDEEFF:128>>)). + hash_256_test() -> ?assertEqual(<<16#22BCE46032802AF0ABFACF3768F7BE04A34F5F01DF60F44FFD52D3CA937350C0:256>>, sha3:hash(256, <<16#00112233445566778899AABBCCDDEEFF:128>>)). +hash_256_native_test() -> + ?assertEqual(<<16#22BCE46032802AF0ABFACF3768F7BE04A34F5F01DF60F44FFD52D3CA937350C0:256>>, + sha3:kek(256, <<16#00112233445566778899AABBCCDDEEFF:128>>)). + hash_384_test() -> ?assertEqual(<<16#25FAC1ADECBE1B254976FE32C2FE78829B23D7D84316141ECD208D6806A9DB4352A014ADA4106BA0D210DDA0FD18E150:384>>, sha3:hash(384, <<16#00112233445566778899AABBCCDDEEFF:128>>)). +hash_384_native_test() -> + ?assertEqual(<<16#25FAC1ADECBE1B254976FE32C2FE78829B23D7D84316141ECD208D6806A9DB4352A014ADA4106BA0D210DDA0FD18E150:384>>, + sha3:kek(384, <<16#00112233445566778899AABBCCDDEEFF:128>>)). + hash_512_test() -> ?assertEqual(<<16#94EE7851163C39C3489373AA0BF885D95925EAD7484C586D2E0D01D9C8069D3C30E2EEA2DC63A91B517FE53E43A31D764A2154A2DA92876366B138ABC4406805:512>>, sha3:hash(512, <<16#00112233445566778899AABBCCDDEEFF:128>>)). -hexhash_224_test() -> - ?assertEqual(<<"038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1">>, - sha3:hexhash(224, <<16#00112233445566778899AABBCCDDEEFF:128>>)). - -hexhash_256_test() -> - ?assertEqual(<<"22BCE46032802AF0ABFACF3768F7BE04A34F5F01DF60F44FFD52D3CA937350C0">>, - sha3:hexhash(256, <<16#00112233445566778899AABBCCDDEEFF:128>>)). - -hexhash_384_test() -> - ?assertEqual(<<"25FAC1ADECBE1B254976FE32C2FE78829B23D7D84316141ECD208D6806A9DB4352A014ADA4106BA0D210DDA0FD18E150">>, - sha3:hexhash(384, <<16#00112233445566778899AABBCCDDEEFF:128>>)). - -hexhash_512_test() -> - ?assertEqual(<<"94EE7851163C39C3489373AA0BF885D95925EAD7484C586D2E0D01D9C8069D3C30E2EEA2DC63A91B517FE53E43A31D764A2154A2DA92876366B138ABC4406805">>, - sha3:hexhash(512, <<16#00112233445566778899AABBCCDDEEFF:128>>)). - +hash_512_native_test() -> + ?assertEqual(<<16#94EE7851163C39C3489373AA0BF885D95925EAD7484C586D2E0D01D9C8069D3C30E2EEA2DC63A91B517FE53E43A31D764A2154A2DA92876366B138ABC4406805:512>>, + sha3:kek(512, <<16#00112233445566778899AABBCCDDEEFF:128>>)). diff --git a/zomp.meta b/zomp.meta new file mode 100644 index 0000000..c3ea7a9 --- /dev/null +++ b/zomp.meta @@ -0,0 +1,17 @@ +{name,"Erlang SHA-3/Keccak"}. +{type,lib}. +{modules,[]}. +{prefix,none}. +{author,"Craig Everett"}. +{desc,"SHA-3 and Keccak in NIF and native Erlang."}. +{package_id,{"otpr","sha3",{0,1,5}}}. +{deps,[]}. +{key_name,none}. +{a_email,"zxq9@zxq9.com"}. +{c_email,"tetsuya.suzuki@gmail.com"}. +{copyright,"SUZUKI Tetsuya"}. +{file_exts,[]}. +{license,"Apache-2.0"}. +{repo_url,"https://github.com/zxq9/erlang-sha3"}. +{tags,["aeternity","sha3","blockchain","keccak"]}. +{ws_url,[]}. diff --git a/zomp_prep b/zomp_prep new file mode 100755 index 0000000..8f5a2b7 --- /dev/null +++ b/zomp_prep @@ -0,0 +1,8 @@ +#! /bin/bash + +# This is a small pre-packaging source generation and include correction script that should be +# run before packaging this project for use with ZX/Zomp. + +rm -rf _build +rm -f ebin/*.beam +rm -f rebar*