From 67c12f5bd16bb541d51a73e98135683ef175cf8d Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 11 Apr 2024 16:25:35 +0400 Subject: [PATCH 01/10] add clang-format style specification Signed-off-by: Anjan Roy --- .clang-format | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..065dcdf --- /dev/null +++ b/.clang-format @@ -0,0 +1,225 @@ +--- +Language: Cpp +# BasedOnStyle: Mozilla +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Mozilla +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + From 3001f55266941e7db1ac124e6ae3d0e75e1cf48b Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 11 Apr 2024 16:26:08 +0400 Subject: [PATCH 02/10] update Makefile for ease of maintainability Signed-off-by: Anjan Roy --- Makefile | 88 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 0b9d65a..3e68295 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,75 @@ -CXX = g++ -CXXFLAGS = -std=c++20 -Wall -Wextra -pedantic -OPTFLAGS = -O3 -march=native -mtune=native -IFLAGS = -I ./include -DEP_IFLAGS = -I ./sha3/include -# From https://gmplib.org/manual/Headers-and-Libraries -LFLAGS = -lgmpxx -lgmp +CXX ?= clang++ +CXX_FLAGS = -std=c++20 +WARN_FLAGS = -Wall -Wextra -pedantic +OPT_FLAGS = -O3 -march=native +LINK_FLAGS = -flto +GMP_LINK_FLAGS = -lgmpxx -lgmp -all: testing +SHA3_INC_DIR = ./sha3/include +I_FLAGS = -I ./include +DEP_IFLAGS = -I $(SHA3_INC_DIR) -test/a.out: test/main.cpp include/*.hpp include/test/*.hpp - $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) $(DEP_IFLAGS) $< -o $@ $(LFLAGS) +SRC_DIR = include +FALCON_SOURCES := $(wildcard $(SRC_DIR)/*.hpp) +BUILD_DIR = build -testing: test/a.out - ./$< +TEST_DIR = tests +TEST_SOURCES := $(wildcard $(TEST_DIR)/*.cpp) +TEST_OBJECTS := $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %.cpp,%.o,$(TEST_SOURCES)))) +TEST_LINK_FLAGS = -lgtest -lgtest_main +TEST_BINARY = $(BUILD_DIR)/test.out +GTEST_PARALLEL = ./gtest-parallel/gtest-parallel -bench/a.out: bench/main.cpp include/*.hpp include/bench/*.hpp - # make sure you've google-benchmark globally installed; - # see https://github.com/google/benchmark/tree/84c71fa#installation - $(CXX) $(CXXFLAGS) $(OPTFLAGS) $(IFLAGS) $(DEP_IFLAGS) $< -o $@ $(LFLAGS) -lbenchmark +BENCHMARK_DIR = benchmarks +BENCHMARK_SOURCES := $(wildcard $(BENCHMARK_DIR)/*.cpp) +BENCHMARK_HEADERS := $(wildcard $(BENCHMARK_DIR)/*.hpp) +BENCHMARK_OBJECTS := $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %.cpp,%.o,$(BENCHMARK_SOURCES)))) +BENCHMARK_LINK_FLAGS = -lbenchmark -lbenchmark_main -lpthread +BENCHMARK_BINARY = $(BUILD_DIR)/bench.out +PERF_LINK_FLAGS = -lbenchmark -lbenchmark_main -lpfm -lpthread +PERF_BINARY = $(BUILD_DIR)/perf.out -benchmark: bench/a.out - ./$< --benchmark_time_unit=us --benchmark_counters_tabular=true +all: test + +$(BUILD_DIR): + mkdir -p $@ + +$(SHA3_INC_DIR): + git submodule update --init + +$(GTEST_PARALLEL): $(SHA3_INC_DIR) + git submodule update --init + +$(BUILD_DIR)/%.o: $(TEST_DIR)/%.cpp $(BUILD_DIR) $(SHA3_INC_DIR) + $(CXX) $(CXX_FLAGS) $(WARN_FLAGS) $(OPT_FLAGS) $(I_FLAGS) $(DEP_IFLAGS) -c $< -o $@ + +$(TEST_BINARY): $(TEST_OBJECTS) + $(CXX) $(OPT_FLAGS) $(LINK_FLAGS) $^ $(TEST_LINK_FLAGS) -o $@ $(GMP_LINK_FLAGS) + +test: $(TEST_BINARY) $(GTEST_PARALLEL) + $(GTEST_PARALLEL) $< --print_test_times + +$(BUILD_DIR)/%.o: $(BENCHMARK_DIR)/%.cpp $(BUILD_DIR) $(SHA3_INC_DIR) + $(CXX) $(CXX_FLAGS) $(WARN_FLAGS) $(OPT_FLAGS) $(I_FLAGS) $(DEP_IFLAGS) -c $< -o $@ + +$(BENCHMARK_BINARY): $(BENCHMARK_OBJECTS) + $(CXX) $(OPT_FLAGS) $(LINK_FLAGS) $^ $(BENCHMARK_LINK_FLAGS) -o $@ $(GMP_LINK_FLAGS) + +benchmark: $(BENCHMARK_BINARY) + # Must *not* build google-benchmark with libPFM + ./$< --benchmark_time_unit=us --benchmark_min_warmup_time=.5 --benchmark_enable_random_interleaving=true --benchmark_repetitions=16 --benchmark_min_time=0.1s --benchmark_display_aggregates_only=true --benchmark_counters_tabular=true + +$(PERF_BINARY): $(BENCHMARK_OBJECTS) + $(CXX) $(OPT_FLAGS) $(LINK_FLAGS) $^ $(PERF_LINK_FLAGS) -o $@ $(GMP_LINK_FLAGS) + +perf: $(PERF_BINARY) + # Must build google-benchmark with libPFM, follow https://gist.github.com/itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7 + ./$< --benchmark_time_unit=us --benchmark_min_warmup_time=.5 --benchmark_enable_random_interleaving=true --benchmark_repetitions=16 --benchmark_min_time=0.1s --benchmark_display_aggregates_only=true --benchmark_counters_tabular=true --benchmark_perf_counters=CYCLES + +.PHONY: format clean clean: - find . -name '*.out' -o -name '*.o' -o -name '*.so' -o -name '*.gch' | xargs rm -rf + rm -rf $(BUILD_DIR) -format: - find . -name '*.hpp' -o -name '*.cpp' -o -name '*.hpp' | xargs clang-format -i --style=Mozilla +format: $(FALCON_SOURCES) $(TEST_SOURCES) $(DUDECT_TEST_SOURCES) $(BENCHMARK_SOURCES) $(BENCHMARK_HEADERS) + clang-format -i $^ From 12c1de78456bac587a883165cfa795bfc86e5923 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 11 Apr 2024 16:37:55 +0400 Subject: [PATCH 03/10] relocate tests to their own directory Preparing for transitioning to google-test framework Signed-off-by: Anjan Roy --- {test => tests}/main.cpp | 2 +- {include/test => tests}/test_encoding.hpp | 0 {include/test => tests}/test_falcon.hpp | 0 {include/test => tests}/test_ff.hpp | 0 {include/test => tests}/test_ffsampling.hpp | 0 {include/test => tests}/test_fft.hpp | 0 {include/test => tests}/test_keygen.hpp | 0 {include/test => tests}/test_ntru_gen.hpp | 0 {include/test => tests}/test_ntt.hpp | 0 {include/test => tests}/test_samplerz.hpp | 0 {include/test => tests}/test_signing.hpp | 0 11 files changed, 1 insertion(+), 1 deletion(-) rename {test => tests}/main.cpp (98%) rename {include/test => tests}/test_encoding.hpp (100%) rename {include/test => tests}/test_falcon.hpp (100%) rename {include/test => tests}/test_ff.hpp (100%) rename {include/test => tests}/test_ffsampling.hpp (100%) rename {include/test => tests}/test_fft.hpp (100%) rename {include/test => tests}/test_keygen.hpp (100%) rename {include/test => tests}/test_ntru_gen.hpp (100%) rename {include/test => tests}/test_ntt.hpp (100%) rename {include/test => tests}/test_samplerz.hpp (100%) rename {include/test => tests}/test_signing.hpp (100%) diff --git a/test/main.cpp b/tests/main.cpp similarity index 98% rename from test/main.cpp rename to tests/main.cpp index 5c50350..795dd1a 100644 --- a/test/main.cpp +++ b/tests/main.cpp @@ -1,4 +1,4 @@ -#include "test/test_falcon.hpp" +#include "test_falcon.hpp" #include int diff --git a/include/test/test_encoding.hpp b/tests/test_encoding.hpp similarity index 100% rename from include/test/test_encoding.hpp rename to tests/test_encoding.hpp diff --git a/include/test/test_falcon.hpp b/tests/test_falcon.hpp similarity index 100% rename from include/test/test_falcon.hpp rename to tests/test_falcon.hpp diff --git a/include/test/test_ff.hpp b/tests/test_ff.hpp similarity index 100% rename from include/test/test_ff.hpp rename to tests/test_ff.hpp diff --git a/include/test/test_ffsampling.hpp b/tests/test_ffsampling.hpp similarity index 100% rename from include/test/test_ffsampling.hpp rename to tests/test_ffsampling.hpp diff --git a/include/test/test_fft.hpp b/tests/test_fft.hpp similarity index 100% rename from include/test/test_fft.hpp rename to tests/test_fft.hpp diff --git a/include/test/test_keygen.hpp b/tests/test_keygen.hpp similarity index 100% rename from include/test/test_keygen.hpp rename to tests/test_keygen.hpp diff --git a/include/test/test_ntru_gen.hpp b/tests/test_ntru_gen.hpp similarity index 100% rename from include/test/test_ntru_gen.hpp rename to tests/test_ntru_gen.hpp diff --git a/include/test/test_ntt.hpp b/tests/test_ntt.hpp similarity index 100% rename from include/test/test_ntt.hpp rename to tests/test_ntt.hpp diff --git a/include/test/test_samplerz.hpp b/tests/test_samplerz.hpp similarity index 100% rename from include/test/test_samplerz.hpp rename to tests/test_samplerz.hpp diff --git a/include/test/test_signing.hpp b/tests/test_signing.hpp similarity index 100% rename from include/test/test_signing.hpp rename to tests/test_signing.hpp From 17cb42cc575e8df9520d16ff55888b9057a7a6b7 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 11 Apr 2024 19:18:11 +0400 Subject: [PATCH 04/10] refactor all tests to use google-test framework Signed-off-by: Anjan Roy --- .../{test_ntru_gen.hpp => check_ntru_eq.hpp} | 32 +---- tests/main.cpp | 64 ---------- .../{test_encoding.hpp => test_encoding.cpp} | 72 +++++++---- tests/test_falcon.hpp | 11 -- tests/{test_ff.hpp => test_ff.cpp} | 30 ++--- ...est_ffsampling.hpp => test_ffsampling.cpp} | 15 +-- tests/{test_fft.hpp => test_fft.cpp} | 115 ++++++++++-------- tests/{test_keygen.hpp => test_keygen.cpp} | 22 ++-- tests/test_ntru_gen.cpp | 36 ++++++ tests/{test_ntt.hpp => test_ntt.cpp} | 14 +-- .../{test_samplerz.hpp => test_samplerz.cpp} | 22 ++-- tests/{test_signing.hpp => test_signing.cpp} | 18 +-- 12 files changed, 202 insertions(+), 249 deletions(-) rename tests/{test_ntru_gen.hpp => check_ntru_eq.hpp} (71%) delete mode 100644 tests/main.cpp rename tests/{test_encoding.hpp => test_encoding.cpp} (87%) delete mode 100644 tests/test_falcon.hpp rename tests/{test_ff.hpp => test_ff.cpp} (64%) rename tests/{test_ffsampling.hpp => test_ffsampling.cpp} (95%) rename tests/{test_fft.hpp => test_fft.cpp} (90%) rename tests/{test_keygen.hpp => test_keygen.cpp} (86%) create mode 100644 tests/test_ntru_gen.cpp rename tests/{test_ntt.hpp => test_ntt.cpp} (91%) rename tests/{test_samplerz.hpp => test_samplerz.cpp} (99%) rename tests/{test_signing.hpp => test_signing.cpp} (74%) diff --git a/tests/test_ntru_gen.hpp b/tests/check_ntru_eq.hpp similarity index 71% rename from tests/test_ntru_gen.hpp rename to tests/check_ntru_eq.hpp index c1a59cf..b8c7335 100644 --- a/tests/test_ntru_gen.hpp +++ b/tests/check_ntru_eq.hpp @@ -1,9 +1,6 @@ #pragma once #include "ntru_gen.hpp" -#include "prng.hpp" -#include -// Test functional correctness of Falcon PQC suite implementation namespace test_falcon { // Check whether computed f, g, F, G ∈ Z[x]/(x^N + 1) actually satisfy NTRU @@ -14,7 +11,7 @@ namespace test_falcon { // though note that for polynomial mutliplication it doesn't use Karatsuba, // rather it performs polynomial arithmetic in frequency domain. template -bool +static inline bool check_ntru_eq(const int32_t* const __restrict f, const int32_t* const __restrict g, const int32_t* const __restrict F, @@ -71,31 +68,4 @@ check_ntru_eq(const int32_t* const __restrict f, return flg; } -// Test functional correctness of NTRUGen routine, by first generating f, g, F, -// G ∈ Z[x]/(x^N + 1) and then solving NTRU equation ( see eq 3.15 of Falcon -// specification ). -// -// Collects some inspiration from -// https://github.com/tprest/falcon.py/blob/88d01ed/test.py#L88-L94 -template -void -test_ntru_gen() -{ - auto f = static_cast(std::malloc(sizeof(int32_t) * N)); - auto g = static_cast(std::malloc(sizeof(int32_t) * N)); - auto F = static_cast(std::malloc(sizeof(int32_t) * N)); - auto G = static_cast(std::malloc(sizeof(int32_t) * N)); - - prng::prng_t rng; - ntru_gen::ntru_gen(f, g, F, G, rng); - const bool flg = check_ntru_eq(f, g, F, G); - - std::free(f); - std::free(g); - std::free(F); - std::free(G); - - assert(flg); -} - } diff --git a/tests/main.cpp b/tests/main.cpp deleted file mode 100644 index 795dd1a..0000000 --- a/tests/main.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "test_falcon.hpp" -#include - -int -main() -{ - test_falcon::test_field_ops(); - std::cout << "[test] Falcon prime field arithmetic\n"; - - test_falcon::test_ntt(); - test_falcon::test_ntt(); - std::cout << "[test] (inverse) Number Theoretic Transform over Z_q\n"; - - test_falcon::test_fft(); - test_falcon::test_fft(); - std::cout << "[test] (inverse) Fast Fourier Transform over Q\n"; - - test_falcon::test_fft_split_merge<2>(); - test_falcon::test_fft_split_merge<3>(); - test_falcon::test_fft_split_merge<4>(); - test_falcon::test_fft_split_merge<5>(); - test_falcon::test_fft_split_merge<6>(); - test_falcon::test_fft_split_merge<7>(); - test_falcon::test_fft_split_merge<8>(); - test_falcon::test_fft_split_merge<9>(); - test_falcon::test_fft_split_merge<10>(); - std::cout << "[test] Splitting and merging of polynomials in FFT form\n"; - - test_falcon::test_falcon512_samplerz(); - test_falcon::test_falcon1024_samplerz(); - std::cout << "[test] Sampler over the Integers, using KATs\n"; - - test_falcon::test_ntru_gen<512>(); - test_falcon::test_ntru_gen<1024>(); - std::cout << "[test] NTRUGen\n"; - - test_falcon::test_encoding_pkey<512>(); - test_falcon::test_encoding_pkey<1024>(); - std::cout << "[test] Encode/ Decode Public Key\n"; - - test_falcon::test_encoding_skey<512>(); - test_falcon::test_encoding_skey<1024>(); - std::cout << "[test] Encode/ Decode Secret Key\n"; - - test_falcon::test_keygen<512>(); - test_falcon::test_keygen<1024>(); - std::cout << "[test] Falcon KeyGen\n"; - - test_falcon::test_ff_sampling<512>(165.736617183, 1.277833697); - test_falcon::test_ff_sampling<1024>(168.388571447, 1.298280334); - std::cout << "[test] Fast Fourier Sampling\n"; - - test_falcon::test_sig_compression<512>(165.736617183, 1.277833697, 34034726); - test_falcon::test_sig_compression<1024>(168.388571447, 1.298280334, 70265242); - test_falcon::test_sig_decompression<512>(); - test_falcon::test_sig_decompression<1024>(); - std::cout << "[test] Signature Compression/ Decompression\n"; - - test_falcon::test_keygen_sign_verify<512>(); - test_falcon::test_keygen_sign_verify<1024>(); - std::cout << "[test] Keygen -> Sign -> Verify\n"; - - return EXIT_SUCCESS; -} diff --git a/tests/test_encoding.hpp b/tests/test_encoding.cpp similarity index 87% rename from tests/test_encoding.hpp rename to tests/test_encoding.cpp index 75f1a70..a0a2dc7 100644 --- a/tests/test_encoding.hpp +++ b/tests/test_encoding.cpp @@ -1,22 +1,18 @@ -#pragma once #include "common.hpp" #include "decoding.hpp" #include "encoding.hpp" #include "ffsampling.hpp" #include "hashing.hpp" #include "keygen.hpp" +#include "ntt.hpp" #include "prng.hpp" -#include -#include #include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Test whether random public key ( as polynomial over Fq | q = 12289 ), can be // correctly encoded/ decoded or not. template -void +static void test_encoding_pkey() { constexpr size_t pklen = falcon_utils::compute_pkey_len(); @@ -41,14 +37,20 @@ test_encoding_pkey() std::free(pkey); std::free(h_); - assert(flg); - assert(success); + EXPECT_TRUE(flg); + EXPECT_TRUE(success); +} + +TEST(Falcon, EncodeDecodePublicKey) +{ + test_encoding_pkey(); + test_encoding_pkey(); } // Test whether randomly generated ( using NTRUGen ) Falcon secret key can be // correctly encoded/ decoded or not. template -void +static void test_encoding_skey() { constexpr size_t sklen = falcon_utils::compute_skey_len(); @@ -61,9 +63,9 @@ test_encoding_skey() auto f_ = static_cast(std::malloc(sizeof(int32_t) * N)); auto g_ = static_cast(std::malloc(sizeof(int32_t) * N)); auto F_ = static_cast(std::malloc(sizeof(int32_t) * N)); - prng::prng_t rng; + prng::prng_t prng; - ntru_gen::ntru_gen(f, g, F, G, rng); + ntru_gen::ntru_gen(f, g, F, G, prng); encoding::encode_skey(f, g, F, skey); const bool flg = decoding::decode_skey(skey, f_, g_, F_); @@ -83,8 +85,14 @@ test_encoding_skey() std::free(g_); std::free(F_); - assert(flg); - assert(success); + EXPECT_TRUE(flg); + EXPECT_TRUE(success); +} + +TEST(Falcon, EncodeDecodeSecretKey) +{ + test_encoding_skey(); + test_encoding_skey(); } // Generate Falcon{512, 1024} signature ( i.e. polynomial s2 ) to ensure that it @@ -94,7 +102,7 @@ test_encoding_skey() // This test partially implements algorithm 10 of Falcon specification, to // ensure correctness of signature compression/ decompression routines. template -void +static void test_sig_compression( const double σ, // Standard deviation ( see table 3.3 of specification ) const double σ_min, // See table 3.3 of specification @@ -130,11 +138,11 @@ test_sig_compression( auto dec_s2 = static_cast(std::malloc(sizeof(int32_t) * N)); auto sig = static_cast(std::malloc(siglen)); auto tmp = static_cast(std::malloc(sizeof(fft::cmplx) * N)); - prng::prng_t rng; + prng::prng_t prng; - keygen::keygen(B, T, h, σ, rng); - rng.read(msg, mlen); - rng.read(salt, salt_len); + keygen::keygen(B, T, h, σ, prng); + prng.read(msg, mlen); + prng.read(salt, salt_len); hashing::hash_to_point(salt, salt_len, msg, mlen, c); for (size_t i = 0; i < N; i++) { @@ -152,7 +160,7 @@ test_sig_compression( while (1) { // ffSampling i.e. compute z = (z0, z1), same as line 6 of algo 10 - ffsampling::ff_sampling()>(t0, t1, T, σ_min, z0, z1, rng); + ffsampling::ff_sampling()>(t0, t1, T, σ_min, z0, z1, prng); // compute tz = (tz0, tz1) = (t0 - z0, t1 - z1) polynomial::sub()>(t0, z0, tz0); @@ -218,8 +226,14 @@ test_sig_compression( std::free(sig); std::free(tmp); - assert(decompressed); - assert(matches); + EXPECT_TRUE(decompressed); + EXPECT_TRUE(matches); +} + +TEST(Falcon, SignatureCompression) +{ + test_sig_compression(165.736617183, 1.277833697, 34034726); + test_sig_compression(168.388571447, 1.298280334, 70265242); } // Generate random signature bytes and attempt to decompress it, see how @@ -227,7 +241,7 @@ test_sig_compression( // to decompress and if it succeeds, it should also be able to compress it // properly - check that situation too. template -void +static void test_sig_decompression() { // See table 3.3 of the specification @@ -237,10 +251,10 @@ test_sig_decompression() auto sig0 = static_cast(std::malloc(siglen)); auto sig1 = static_cast(std::malloc(siglen)); auto s2 = static_cast(std::malloc(sizeof(int32_t) * N)); - prng::prng_t rng; + prng::prng_t prng; // generate random signature bytes - rng.read(sig0, siglen); + prng.read(sig0, siglen); // attempt to decompress random signature const bool decompressed = decoding::decompress_sig(sig0, s2); @@ -248,7 +262,7 @@ test_sig_decompression() if (decompressed) { // if anyhow decompressed, we should be able to compress it too const bool compressed = encoding::compress_sig(s2, sig1); - assert(compressed); + EXPECT_TRUE(compressed); // if compressed, both should produce same signature // @@ -259,7 +273,7 @@ test_sig_decompression() matches &= sig0[i] == sig1[i]; } - assert(matches); + EXPECT_TRUE(matches); } std::free(sig0); @@ -267,4 +281,8 @@ test_sig_decompression() std::free(s2); } +TEST(Falcon, SignatureDecompression) +{ + test_sig_decompression(); + test_sig_decompression(); } diff --git a/tests/test_falcon.hpp b/tests/test_falcon.hpp deleted file mode 100644 index 6395b9c..0000000 --- a/tests/test_falcon.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "test_encoding.hpp" -#include "test_ff.hpp" -#include "test_ffsampling.hpp" -#include "test_fft.hpp" -#include "test_keygen.hpp" -#include "test_ntru_gen.hpp" -#include "test_ntt.hpp" -#include "test_samplerz.hpp" -#include "test_signing.hpp" diff --git a/tests/test_ff.hpp b/tests/test_ff.cpp similarity index 64% rename from tests/test_ff.hpp rename to tests/test_ff.cpp index c5e50ce..7b8a7f5 100644 --- a/tests/test_ff.hpp +++ b/tests/test_ff.cpp @@ -1,17 +1,13 @@ -#pragma once #include "ff.hpp" -#include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Test functional correctness of Falcon prime field operations, by running -// through multiple rounds ( see template parameter ) of execution of field -// arithmetic, on randomly sampled field elements -template -static void -test_field_ops() +// through multiple rounds of execution of field arithmetic, on randomly sampled +// field elements. +TEST(Falcon, ArithmeticOverZq) { + constexpr size_t rounds = 1024ul; + std::random_device rd; std::mt19937_64 gen(rd()); std::uniform_int_distribution dis{ 0ul, 1ul << 20 }; @@ -25,25 +21,25 @@ test_field_ops() const auto d = -b; const auto e = a + d; - assert(c == e); + EXPECT_EQ(c, e); // multiplication, division, inversion const auto f = a * b; const auto g = f / b; if (b == ff::ff_t::zero()) { - assert(g == ff::ff_t::zero()); + EXPECT_EQ(g, ff::ff_t::zero()); } else { - assert(g == a); + EXPECT_EQ(g, a); } const auto h = a.inv(); const auto k = h * a; if (a == ff::ff_t::zero()) { - assert(k == ff::ff_t::zero()); + EXPECT_EQ(k, ff::ff_t::zero()); } else { - assert(k == ff::ff_t::one()); + EXPECT_EQ(k, ff::ff_t::one()); } // exponentiation, multiplication @@ -55,8 +51,6 @@ test_field_ops() res = res * a; } - assert(res == l); + EXPECT_EQ(res, l); } } - -} diff --git a/tests/test_ffsampling.hpp b/tests/test_ffsampling.cpp similarity index 95% rename from tests/test_ffsampling.hpp rename to tests/test_ffsampling.cpp index dd15f65..ac178bd 100644 --- a/tests/test_ffsampling.hpp +++ b/tests/test_ffsampling.cpp @@ -1,11 +1,8 @@ -#pragma once #include "ffsampling.hpp" #include "keygen.hpp" +#include "ntt.hpp" #include "prng.hpp" -#include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Check whether we can successfully generate two polynomials (s1, s2) each of // degree-N s.t. they satisfy the equation s1 + s2 * h = c ( mod q ), given @@ -18,7 +15,7 @@ namespace test_falcon { // correct and it works as expected by attempting to **partially** implement // Falcon signing algorithm ( algo 10 in specification ). template -void +static void test_ff_sampling( const double σ, // Standard deviation ( see table 3.3 of specification ) const double σ_min // See table 3.3 of specification @@ -136,7 +133,11 @@ test_ff_sampling( std::free(tmp0); std::free(tmp1); - assert(match); + EXPECT_TRUE(match); } +TEST(Falcon, FastFourierSampling) +{ + test_ff_sampling(165.736617183, 1.277833697); + test_ff_sampling(168.388571447, 1.298280334); } diff --git a/tests/test_fft.hpp b/tests/test_fft.cpp similarity index 90% rename from tests/test_fft.hpp rename to tests/test_fft.cpp index 90e4781..6773fad 100644 --- a/tests/test_fft.hpp +++ b/tests/test_fft.cpp @@ -1,51 +1,7 @@ -#pragma once #include "fft.hpp" #include "polynomial.hpp" -#include #include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { - -// Splits a polynomial f into two polynomials f0, f1 s.t. all these polynomials -// are in their coefficient representation. -// -// This routine is an implementation of equation 3.20, described in section 3.6, -// on page 28 of the Falcon specification https://falcon-sign.info/falcon.pdf -template -inline void -split(const fft::cmplx* const __restrict f, - fft::cmplx* const __restrict f0, - fft::cmplx* const __restrict f1) -{ - constexpr size_t n = 1ul << lgn; - constexpr size_t hn = n >> 1; - - for (size_t i = 0; i < hn; i++) { - f0[i] = f[2 * i]; - f1[i] = f[2 * i + 1]; - } -} - -// Merges two polynomials f0, f1 into a single one f s.t. all these polynomials -// are in their coefficient representation. -// -// This routine is an implementation of equation 3.22, described in section 3.6, -// on page 28 of the Falcon specification https://falcon-sign.info/falcon.pdf -template -inline void -merge(const fft::cmplx* const __restrict f0, - const fft::cmplx* const __restrict f1, - fft::cmplx* const __restrict f) -{ - constexpr size_t n = 1ul << lgn; - constexpr size_t hn = n >> 1; - - for (size_t i = 0; i < hn; i++) { - f[2 * i + 0] = f0[i]; - f[2 * i + 1] = f1[i]; - } -} +#include // Ensure functional correctness of (i)FFT implementation, using polynomial // multiplication and division in FFT form, over C @@ -53,7 +9,7 @@ merge(const fft::cmplx* const __restrict f0, // Test is adapted from // https://github.com/tprest/falcon.py/blob/88d01ed/test.py#L46-L59 template -void +static void test_fft() { constexpr size_t n = 1ul << lgn; @@ -105,7 +61,53 @@ test_fft() std::free(fft_c); std::free(fft_d); - assert(!flg); + EXPECT_FALSE(flg); +} + +TEST(Falcon, PolynomialArithmeticInFFTDomain) +{ + test_fft(); + test_fft(); +} + +// Splits a polynomial f into two polynomials f0, f1 s.t. all these polynomials +// are in their coefficient representation. +// +// This routine is an implementation of equation 3.20, described in section 3.6, +// on page 28 of the Falcon specification https://falcon-sign.info/falcon.pdf +template +static inline void +split(const fft::cmplx* const __restrict f, + fft::cmplx* const __restrict f0, + fft::cmplx* const __restrict f1) +{ + constexpr size_t n = 1ul << lgn; + constexpr size_t hn = n >> 1; + + for (size_t i = 0; i < hn; i++) { + f0[i] = f[2 * i]; + f1[i] = f[2 * i + 1]; + } +} + +// Merges two polynomials f0, f1 into a single one f s.t. all these polynomials +// are in their coefficient representation. +// +// This routine is an implementation of equation 3.22, described in section 3.6, +// on page 28 of the Falcon specification https://falcon-sign.info/falcon.pdf +template +static inline void +merge(const fft::cmplx* const __restrict f0, + const fft::cmplx* const __restrict f1, + fft::cmplx* const __restrict f) +{ + constexpr size_t n = 1ul << lgn; + constexpr size_t hn = n >> 1; + + for (size_t i = 0; i < hn; i++) { + f[2 * i + 0] = f0[i]; + f[2 * i + 1] = f1[i]; + } } // Ensure that splitting and merging of polynomials in their FFT representation @@ -113,7 +115,7 @@ test_fft() // between split, merge, split_fft, merge_fft, FFT and iFFT routines, on page 30 // of the Falcon specification https://falcon-sign.info/falcon.pdf template -void +static void test_fft_split_merge() { constexpr bool flg = lgn >= 2 && lgn <= 10; @@ -192,9 +194,20 @@ test_fft_split_merge() std::free(ifft_f0); std::free(ifft_f1); - assert(!flg0); - assert(!flg1); - assert(!flg2); + EXPECT_FALSE(flg0); + EXPECT_FALSE(flg1); + EXPECT_FALSE(flg2); } +TEST(Falcon, PolynomialSplitAndMergeInFFTDomain) +{ + test_fft_split_merge<2>(); + test_fft_split_merge<3>(); + test_fft_split_merge<4>(); + test_fft_split_merge<5>(); + test_fft_split_merge<6>(); + test_fft_split_merge<7>(); + test_fft_split_merge<8>(); + test_fft_split_merge<9>(); + test_fft_split_merge<10>(); } diff --git a/tests/test_keygen.hpp b/tests/test_keygen.cpp similarity index 86% rename from tests/test_keygen.hpp rename to tests/test_keygen.cpp index d5a3d50..dc89138 100644 --- a/tests/test_keygen.hpp +++ b/tests/test_keygen.cpp @@ -1,15 +1,11 @@ -#pragma once +#include "check_ntru_eq.hpp" #include "decoding.hpp" #include "encoding.hpp" #include "falcon.hpp" #include "ntru_gen.hpp" +#include "ntt.hpp" #include "prng.hpp" -#include "test_ntru_gen.hpp" -#include -#include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Test if Falcon Key Generation Algorithm works as expected by doing following // @@ -20,7 +16,7 @@ namespace test_falcon { // - Check if NTRU equation still satisfies or not // - Also ensure that actual G and recomputed G' matches template -void +static void test_keygen() { constexpr size_t sklen = falcon_utils::compute_skey_len(); @@ -45,7 +41,7 @@ test_keygen() // Recompute G using NTRU equation falcon::recompute_G(f_, g_, F_, G_); // See if NTRU equation can be solved - const bool flg = check_ntru_eq(f_, g_, F_, G_); + const bool flg = test_falcon::check_ntru_eq(f_, g_, F_, G_); // Ensure that each coefficient of original G and recomputed G' matches bool match = true; @@ -63,8 +59,12 @@ test_keygen() std::free(G_); std::free(skey); - assert(flg); - assert(match); + EXPECT_TRUE(flg); + EXPECT_TRUE(match); } +TEST(Falcon, KeyGeneration) +{ + test_keygen(); + test_keygen(); } diff --git a/tests/test_ntru_gen.cpp b/tests/test_ntru_gen.cpp new file mode 100644 index 0000000..b962a65 --- /dev/null +++ b/tests/test_ntru_gen.cpp @@ -0,0 +1,36 @@ +#include "check_ntru_eq.hpp" +#include "prng.hpp" +#include + +// Test functional correctness of NTRUGen routine, by first generating f, g, F, +// G ∈ Z[x]/(x^N + 1) and then solving NTRU equation ( see eq 3.15 of Falcon +// specification ). +// +// Collects some inspiration from +// https://github.com/tprest/falcon.py/blob/88d01ed/test.py#L88-L94 +template +static void +test_ntru_gen() +{ + auto f = static_cast(std::malloc(sizeof(int32_t) * N)); + auto g = static_cast(std::malloc(sizeof(int32_t) * N)); + auto F = static_cast(std::malloc(sizeof(int32_t) * N)); + auto G = static_cast(std::malloc(sizeof(int32_t) * N)); + + prng::prng_t prng; + ntru_gen::ntru_gen(f, g, F, G, prng); + const bool flg = test_falcon::check_ntru_eq(f, g, F, G); + + std::free(f); + std::free(g); + std::free(F); + std::free(G); + + EXPECT_TRUE(flg); +} + +TEST(Falcon, NTRUGen) +{ + test_ntru_gen(); + test_ntru_gen(); +} diff --git a/tests/test_ntt.hpp b/tests/test_ntt.cpp similarity index 91% rename from tests/test_ntt.hpp rename to tests/test_ntt.cpp index 70fc157..78a400d 100644 --- a/tests/test_ntt.hpp +++ b/tests/test_ntt.cpp @@ -1,10 +1,6 @@ -#pragma once #include "polynomial.hpp" -#include #include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Ensure functional correctness of (i)NTT implementation, using polynomial // multiplication and division over Z_q @@ -12,7 +8,7 @@ namespace test_falcon { // Test is adapted from // https://github.com/tprest/falcon.py/blob/88d01ed/test.py#L62-L77 template -void +static void test_ntt() { const size_t n = 1ul << lgn; @@ -71,7 +67,11 @@ test_ntt() std::free(ntt_c); std::free(ntt_d); - assert(!flg); + EXPECT_FALSE(flg); } +TEST(Falcon, NumberTheoreticTransform) +{ + test_ntt(); + test_ntt(); } diff --git a/tests/test_samplerz.hpp b/tests/test_samplerz.cpp similarity index 99% rename from tests/test_samplerz.hpp rename to tests/test_samplerz.cpp index 15ab6e9..6d1a307 100644 --- a/tests/test_samplerz.hpp +++ b/tests/test_samplerz.cpp @@ -1,9 +1,5 @@ -#pragma once #include "samplerz.hpp" -#include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Generic struct for holding input and expected output of samplerZ routine, // targeting both Falcon512, Falcon1024 parameter sets. @@ -15633,8 +15629,7 @@ const samplerz_kat_t falcon1024_samplerz_kats[]{ // Test that samplerZ routine is correctly implemented using Falcon512 parameter // set and Known Answer Tests, submitted along with Falcon's NIST submission // package. -void -test_falcon512_samplerz() +TEST(Falcon, Falcon512SamplerZKnownAnswerTests) { for (auto kat : falcon512_samplerz_kats) { std::vector rbytes(kat.rbytes.length() / 2, 0); @@ -15648,16 +15643,15 @@ test_falcon512_samplerz() const auto [z, blen] = samplerz::samplerz(μ, σ_prime, σ_min, data, dlen); - assert(dlen == blen); // ensure all random bytes were consumed - assert(z == kat.z); // ensure sampled z matches expected z ∈ Z + EXPECT_EQ(dlen, blen); // ensure all random bytes were consumed + EXPECT_EQ(z, kat.z); // ensure sampled z matches expected z ∈ Z } } // Test that samplerZ routine is correctly implemented using Falcon1024 // parameter set and Known Answer Tests, submitted along with Falcon's NIST // submission package. -void -test_falcon1024_samplerz() +TEST(Falcon, Falcon1024SamplerZKnownAnswerTests) { for (auto kat : falcon1024_samplerz_kats) { std::vector rbytes(kat.rbytes.length() / 2, 0); @@ -15671,9 +15665,7 @@ test_falcon1024_samplerz() const auto [z, blen] = samplerz::samplerz(μ, σ_prime, σ_min, data, dlen); - assert(dlen == blen); // ensure all random bytes were consumed - assert(z == kat.z); // ensure sampled z matches expected z ∈ Z + EXPECT_EQ(dlen, blen); // ensure all random bytes were consumed + EXPECT_EQ(z, kat.z); // ensure sampled z matches expected z ∈ Z } } - -} diff --git a/tests/test_signing.hpp b/tests/test_signing.cpp similarity index 74% rename from tests/test_signing.hpp rename to tests/test_signing.cpp index 0d324e4..411351b 100644 --- a/tests/test_signing.hpp +++ b/tests/test_signing.cpp @@ -1,11 +1,8 @@ -#pragma once #include "common.hpp" #include "falcon.hpp" +#include "ntt.hpp" #include "prng.hpp" -#include - -// Test functional correctness of Falcon PQC suite implementation -namespace test_falcon { +#include // Generates random Falcon{512, 1024} keypair, takes random message bytes of // length ∈ [0, 1024), signs message and attempts to verify - all should work. @@ -18,6 +15,9 @@ test_keygen_sign_verify() constexpr size_t sklen = falcon_utils::compute_skey_len(); constexpr size_t siglen = falcon_utils::compute_sig_len(); + constexpr size_t min_msg_len = 1; + constexpr size_t max_msg_len = 1024; + auto pkey = static_cast(std::malloc(pklen)); auto skey = static_cast(std::malloc(sklen)); auto sig = static_cast(std::malloc(siglen)); @@ -25,14 +25,14 @@ test_keygen_sign_verify() falcon::keygen(pkey, skey); - for (size_t mlen = 0; mlen < 1024; mlen++) { + for (size_t mlen = min_msg_len; mlen <= max_msg_len; mlen++) { auto msg = static_cast(std::malloc(mlen)); rng.read(msg, mlen); const bool _signed = falcon::sign(skey, msg, mlen, sig); const bool _verified = falcon::verify(pkey, msg, mlen, sig); - assert(_signed && _verified); + EXPECT_TRUE(_signed && _verified); std::free(msg); } @@ -41,4 +41,8 @@ test_keygen_sign_verify() std::free(sig); } +TEST(Falcon, KeygenSignVerify) +{ + test_keygen_sign_verify(); + test_keygen_sign_verify(); } From 657e8255f165bc147480c0cef7efdcf9ea71216b Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 11 Apr 2024 19:20:26 +0400 Subject: [PATCH 05/10] add gtest-parallel as a git submodule dependency This will help us running google-test -based tests faster Signed-off-by: Anjan Roy --- .gitmodules | 3 +++ Makefile | 4 ++-- gtest-parallel | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) create mode 160000 gtest-parallel diff --git a/.gitmodules b/.gitmodules index 184e184..8e85d6c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "sha3"] path = sha3 url = https://github.com/itzmeanjan/sha3.git +[submodule "gtest-parallel"] + path = gtest-parallel + url = https://github.com/google/gtest-parallel.git diff --git a/Makefile b/Makefile index 3e68295..887139c 100644 --- a/Makefile +++ b/Makefile @@ -35,10 +35,10 @@ $(BUILD_DIR): mkdir -p $@ $(SHA3_INC_DIR): - git submodule update --init + git submodule update --init sha3 $(GTEST_PARALLEL): $(SHA3_INC_DIR) - git submodule update --init + git submodule update --init gtest-parallel $(BUILD_DIR)/%.o: $(TEST_DIR)/%.cpp $(BUILD_DIR) $(SHA3_INC_DIR) $(CXX) $(CXX_FLAGS) $(WARN_FLAGS) $(OPT_FLAGS) $(I_FLAGS) $(DEP_IFLAGS) -c $< -o $@ diff --git a/gtest-parallel b/gtest-parallel new file mode 160000 index 0000000..96f4f90 --- /dev/null +++ b/gtest-parallel @@ -0,0 +1 @@ +Subproject commit 96f4f904922f9bf66689e749c40f314845baaac8 From 34d9f1a4050b7b09dd33ecadeaf09592fff86840 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 12 Apr 2024 12:09:56 +0400 Subject: [PATCH 06/10] use `std::fill_n` instead of `std::memset` Signed-off-by: Anjan Roy --- include/decoding.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/decoding.hpp b/include/decoding.hpp index bac749c..2890634 100644 --- a/include/decoding.hpp +++ b/include/decoding.hpp @@ -1,7 +1,9 @@ #pragma once #include "common.hpp" #include "utils.hpp" +#include #include +#include // Falcon KeyPair and Signature Decoding Routines namespace decoding { @@ -25,7 +27,7 @@ decode_pkey(const uint8_t* const __restrict pkey, ff::ff_t* const __restrict h) constexpr uint8_t mask2 = 0x03; if (pkey[0] != header) [[unlikely]] { - std::memset(h, 0, sizeof(ff::ff_t) * N); + std::fill_n(h, N, 0); return false; } @@ -63,9 +65,9 @@ decode_skey(const uint8_t* const __restrict skey, constexpr uint8_t header = 0x50 | static_cast(log2()); if (skey[0] != header) [[unlikely]] { - std::memset(f, 0, sizeof(int32_t) * N); - std::memset(g, 0, sizeof(int32_t) * N); - std::memset(F, 0, sizeof(int32_t) * N); + std::fill_n(f, N, 0); + std::fill_n(g, N, 0); + std::fill_n(F, N, 0); return false; } From b252dd3b98220b03489b02222790ba92351e247c Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 12 Apr 2024 12:34:34 +0400 Subject: [PATCH 07/10] refactor benchmarks, move them to their own directory Signed-off-by: Anjan Roy --- bench/main.cpp | 15 -------- benchmarks/bench_helper.hpp | 10 ++++++ .../bench_keygen.cpp | 17 +++++---- .../bench_signing.cpp | 35 ++++++++++++------- .../bench_verify.cpp | 26 ++++++++------ include/bench/bench_falcon.hpp | 5 --- include/bench/bench_samplerz.hpp | 31 ---------------- 7 files changed, 59 insertions(+), 80 deletions(-) delete mode 100644 bench/main.cpp create mode 100644 benchmarks/bench_helper.hpp rename include/bench/bench_keygen.hpp => benchmarks/bench_keygen.cpp (72%) rename include/bench/bench_signing.hpp => benchmarks/bench_signing.cpp (82%) rename include/bench/bench_verify.hpp => benchmarks/bench_verify.cpp (75%) delete mode 100644 include/bench/bench_falcon.hpp delete mode 100644 include/bench/bench_samplerz.hpp diff --git a/bench/main.cpp b/bench/main.cpp deleted file mode 100644 index bc03c37..0000000 --- a/bench/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "bench/bench_falcon.hpp" - -// register for benchmarking Falcon512 -BENCHMARK(bench_falcon::keygen<512>); -BENCHMARK(bench_falcon::sign_single<512>)->Arg(32); -BENCHMARK(bench_falcon::sign_many<512>)->Arg(32); -BENCHMARK(bench_falcon::verify<512>)->Arg(32); - -// register for benchmarking Falcon1024 -BENCHMARK(bench_falcon::keygen<1024>); -BENCHMARK(bench_falcon::sign_single<1024>)->Arg(32); -BENCHMARK(bench_falcon::sign_many<1024>)->Arg(32); -BENCHMARK(bench_falcon::verify<1024>)->Arg(32); - -BENCHMARK_MAIN(); diff --git a/benchmarks/bench_helper.hpp b/benchmarks/bench_helper.hpp new file mode 100644 index 0000000..472efba --- /dev/null +++ b/benchmarks/bench_helper.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +const auto compute_min = [](const std::vector& v) -> double { + return *std::min_element(v.begin(), v.end()); +}; +const auto compute_max = [](const std::vector& v) -> double { + return *std::max_element(v.begin(), v.end()); +}; diff --git a/include/bench/bench_keygen.hpp b/benchmarks/bench_keygen.cpp similarity index 72% rename from include/bench/bench_keygen.hpp rename to benchmarks/bench_keygen.cpp index 8ea6729..d75b28b 100644 --- a/include/bench/bench_keygen.hpp +++ b/benchmarks/bench_keygen.cpp @@ -1,17 +1,14 @@ -#pragma once +#include "bench_helper.hpp" #include "falcon.hpp" #include -// Benchmark Falcon PQC suite implementation -namespace bench_falcon { - // Benchmark Falcon{512, 1024} keypair generation algorithm. // // Note, this keygen API neither builds matrix B nor Falcon tree T, which are // required for Falcon message signing. template -void -keygen(benchmark::State& state) +static void +falcon_keygen(benchmark::State& state) requires((N == 512) || (N == 1024)) { constexpr size_t pklen = falcon_utils::compute_pkey_len(); @@ -34,4 +31,10 @@ keygen(benchmark::State& state) std::free(skey); } -} +BENCHMARK(falcon_keygen<512>) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); + +BENCHMARK(falcon_keygen<1024>) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); diff --git a/include/bench/bench_signing.hpp b/benchmarks/bench_signing.cpp similarity index 82% rename from include/bench/bench_signing.hpp rename to benchmarks/bench_signing.cpp index aef63b6..6f42255 100644 --- a/include/bench/bench_signing.hpp +++ b/benchmarks/bench_signing.cpp @@ -1,12 +1,9 @@ -#pragma once +#include "bench_helper.hpp" #include "falcon.hpp" #include "prng.hpp" #include #include -// Benchmark Falcon PQC suite implementation -namespace bench_falcon { - // Benchmark Falcon{512, 1024} message signing algorithm, emulating only single // message is signed with secret key. // @@ -14,7 +11,7 @@ namespace bench_falcon { // asked to sign a message, by decoding Falcon secret key. template void -sign_single(benchmark::State& state) +falcon_sign_single(benchmark::State& state) requires((N == 512) || (N == 1024)) { const size_t mlen = state.range(); @@ -32,15 +29,13 @@ sign_single(benchmark::State& state) falcon::keygen(pkey, skey); rng.read(msg, mlen); + bool _signed = true; for (auto _ : state) { - const bool _signed = falcon::sign(skey, msg, mlen, sig); + _signed &= falcon::sign(skey, msg, mlen, sig); benchmark::DoNotOptimize(_signed); - assert(_signed); - benchmark::DoNotOptimize(skey); benchmark::DoNotOptimize(msg); - benchmark::DoNotOptimize(mlen); benchmark::DoNotOptimize(sig); benchmark::ClobberMemory(); } @@ -54,6 +49,7 @@ sign_single(benchmark::State& state) std::free(sig); std::free(msg); + assert(_signed); assert(verified); } @@ -66,7 +62,7 @@ sign_single(benchmark::State& state) // result. template void -sign_many(benchmark::State& state) +falcon_sign_many(benchmark::State& state) requires((N == 512) || (N == 1024)) { const size_t mlen = state.range(); @@ -99,7 +95,6 @@ sign_many(benchmark::State& state) benchmark::DoNotOptimize(B); benchmark::DoNotOptimize(T); benchmark::DoNotOptimize(msg); - benchmark::DoNotOptimize(mlen); benchmark::DoNotOptimize(sig); benchmark::DoNotOptimize(rng); benchmark::ClobberMemory(); @@ -118,4 +113,20 @@ sign_many(benchmark::State& state) assert(verified); } -} +BENCHMARK(falcon_sign_single<512>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); +BENCHMARK(falcon_sign_many<512>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); + +BENCHMARK(falcon_sign_single<1024>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); +BENCHMARK(falcon_sign_many<1024>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); diff --git a/include/bench/bench_verify.hpp b/benchmarks/bench_verify.cpp similarity index 75% rename from include/bench/bench_verify.hpp rename to benchmarks/bench_verify.cpp index febd98f..e9730d5 100644 --- a/include/bench/bench_verify.hpp +++ b/benchmarks/bench_verify.cpp @@ -1,19 +1,16 @@ -#pragma once +#include "bench_helper.hpp" #include "falcon.hpp" #include "prng.hpp" #include #include -// Benchmark Falcon PQC suite implementation -namespace bench_falcon { - // Benchmark Falcon{512, 1024} signature verification algorithm. // // Note, this verification API decodes public key everytime signature // verification is requested. template void -verify(benchmark::State& state) +falcon_verify(benchmark::State& state) requires((N == 512) || (N == 1024)) { const size_t mlen = state.range(); @@ -30,18 +27,17 @@ verify(benchmark::State& state) falcon::keygen(pkey, skey); rng.read(msg, mlen); + const bool _signed = falcon::sign(skey, msg, mlen, sig); assert(_signed); + bool verified = true; for (auto _ : state) { - const bool verified = falcon::verify(pkey, msg, mlen, sig); + verified &= falcon::verify(pkey, msg, mlen, sig); benchmark::DoNotOptimize(verified); - assert(verified); - benchmark::DoNotOptimize(pkey); benchmark::DoNotOptimize(msg); - benchmark::DoNotOptimize(mlen); benchmark::DoNotOptimize(sig); benchmark::ClobberMemory(); } @@ -52,6 +48,16 @@ verify(benchmark::State& state) std::free(skey); std::free(sig); std::free(msg); -} + assert(verified); } + +BENCHMARK(falcon_verify<512>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); + +BENCHMARK(falcon_verify<1024>) + ->Arg(32) + ->ComputeStatistics("min", compute_min) + ->ComputeStatistics("max", compute_max); diff --git a/include/bench/bench_falcon.hpp b/include/bench/bench_falcon.hpp deleted file mode 100644 index 52d231f..0000000 --- a/include/bench/bench_falcon.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "bench_keygen.hpp" -#include "bench_signing.hpp" -#include "bench_verify.hpp" diff --git a/include/bench/bench_samplerz.hpp b/include/bench/bench_samplerz.hpp deleted file mode 100644 index 9423a3f..0000000 --- a/include/bench/bench_samplerz.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "samplerz.hpp" -#include - -// Benchmark Falcon PQC suite implementation -namespace bench_falcon { - -// Benchmarks Sampler over the Integers for some specific μ, σ' and σ_min -inline void -samplerz(benchmark::State& state) -{ - constexpr double μ = -91.90471153063714; - constexpr double σ_prime = 1.7037990414754918; - constexpr double σ_min = 1.2778336969128337; - prng::prng_t rng; - - for (auto _ : state) { - const auto res = samplerz::samplerz(μ, σ_prime, σ_min, rng); - - benchmark::DoNotOptimize(res); - benchmark::DoNotOptimize(μ); - benchmark::DoNotOptimize(σ_prime); - benchmark::DoNotOptimize(σ_min); - benchmark::DoNotOptimize(rng); - benchmark::ClobberMemory(); - } - - state.SetItemsProcessed(static_cast(state.iterations())); -} - -} From edcbf402bb072e5eaace050e99518f3694600499 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 12 Apr 2024 13:08:30 +0400 Subject: [PATCH 08/10] move examples to different directory Signed-off-by: Anjan Roy --- {example => examples}/sign_many.cpp | 0 {example => examples}/sign_one.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {example => examples}/sign_many.cpp (100%) rename {example => examples}/sign_one.cpp (100%) diff --git a/example/sign_many.cpp b/examples/sign_many.cpp similarity index 100% rename from example/sign_many.cpp rename to examples/sign_many.cpp diff --git a/example/sign_one.cpp b/examples/sign_one.cpp similarity index 100% rename from example/sign_one.cpp rename to examples/sign_one.cpp From 7a2a8cc264da92c37d843087edea0f15e84241d7 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 12 Apr 2024 13:08:51 +0400 Subject: [PATCH 09/10] update project documentation to reflect latest state Signed-off-by: Anjan Roy --- README.md | 184 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 069147c..258e0a8 100644 --- a/README.md +++ b/README.md @@ -25,43 +25,29 @@ Here I'm maintaining a header-only C++ library implementing Falcon512 and Falcon Falcon specification, which I thoroughly followed during this work, can be found @ https://falcon-sign.info/falcon.pdf. I suggest you go through that for having an in-depth understanding of Falcon DSA. -> **Note** You may wish to follow progress of NIST PQC standardization effort @ https://csrc.nist.gov/projects/post-quantum-cryptography. - ## Prerequisites -- A C++ compiler with support for C++20 standard library +- A C++ compiler with support for C++20 standard library. ```bash -$ clang++ --version -Apple clang version 14.0.0 (clang-1400.0.29.202) -Target: x86_64-apple-darwin22.2.0 +$ clang++ -v +Ubuntu clang version 17.0.2 (1~exp1ubuntu2.1) +Target: x86_64-pc-linux-gnu Thread model: posix -InstalledDir: /Library/Developer/CommandLineTools/usr/bin +InstalledDir: /usr/bin -$ g++ --version -g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0 +$ g++ -v +gcc version 13.2.0 (Ubuntu 13.2.0-4ubuntu3) ``` -- System development utilities such as `make` and `cmake` +- System development utilities such as `make`, `cmake` ```bash $ make --version GNU Make 4.3 $ cmake --version -cmake version 3.22.1 -``` - -- SHAKE256 XOF from `sha3` library is used for hashing message ( input to sign/ verify routine ) to a lattice point. `sha3` itself is a zero-dependency, header-only C++ library which is pinned to some specific commit using git submodule. For importing `sha3`, issue following commands after cloning this repository. - -```bash -# Assuming repository is already cloned, if not try -# -# git clone https://github.com/itzmeanjan/falcon.git - -pushd falcon -git submodule update --init -popd +cmake version 3.27.4 ``` - Falcon key generation algorithm requires us to solve NTRU equation ( see equation 3.15 of Falcon specification ) which needs arbitrary precision integer ( i.e. big integer ) arithmetic support. For that purpose I use GNU MP library's C++ interface. Find more @ https://gmplib.org/manual. Install GMP header files and library using following commands. @@ -71,64 +57,132 @@ sudo apt-get install -y libgmp-dev # On Ubuntu/ Debian brew install gmp # On MacOS ``` -- For benchmarking Falcon key generation/ signing/ verification routines, targeting CPU systems, you'll need `google-benchmark` header files and library (globally) installed. Follow https://github.com/google/benchmark/tree/b111d01c#installation for installation guideline. +- For testing correctness and compatibility of this Falcon DSA implementation, you need to (globally) install `google-test` library and headers. Follow guide @ https://github.com/google/googletest/tree/main/googletest#standalone-cmake-project, if you don't have it installed. +vvccccvufjefnghncirgbu +- For benchmarking Falcon key generation, signing and verification routines, targeting CPU systems, you'll need `google-benchmark` header files and library (globally) installed. Follow https://github.com/google/benchmark#installation for installation guideline. + +> [!NOTE] +> If you are on a machine running GNU/Linux kernel and you want to obtain CPU cycle count for DSA routines, you should consider building `google-benchmark` library with `libPFM` support, following https://gist.github.com/itzmeanjan/05dc3e946f635d00c5e0b21aae6203a7, a step-by-step guide. Find more about libPFM @ https://perfmon2.sourceforge.net. + +> [!TIP] +> Git submodule based dependencies will generally be imported automatically, but in case that doesn't work, you can manually initialize and update them all by issuing `$ git submodule update --init` from inside the root of this repository. ## Testing For ensuring functional correctness of Falcon implementation ( along with its components such as `NTRUGen`, `NTRUSolve`, `samplerZ` or `ffSampling` etc. ) issue -> **Warning** This implementation of Falcon is not yet tested to be **conformant** with NIST submission of Falcon - that's because I've not yet tested it with **K**nown **A**nswer **T**ests which are present in Falcon submission package. +> [!CAUTION] +> This implementation of Falcon DSA is not yet tested to be **conformant** with NIST submission of Falcon - that's because I've not yet tested it with **K**nown **A**nswer **T**ests which are present in Falcon submission package. ```bash -make - -[test] Falcon prime field arithmetic -[test] (inverse) Number Theoretic Transform over Z_q -[test] (inverse) Fast Fourier Transform over Q -[test] Splitting and merging of polynomials in FFT form -[test] Sampler over the Integers, using KATs -[test] NTRUGen -[test] Encode/ Decode Public Key -[test] Encode/ Decode Secret Key -[test] Falcon KeyGen -[test] Fast Fourier Sampling -[test] Signature Compression/ Decompression -[test] Keygen -> Sign -> Verify +make -j +``` + +```bash +[14/14] Falcon.KeygenSignVerify (4572 ms) +PASSED TESTS (14/14): + 4 ms: build/test.out Falcon.PolynomialSplitAndMergeInFFTDomain + 4 ms: build/test.out Falcon.SignatureDecompression + 4 ms: build/test.out Falcon.PolynomialArithmeticInFFTDomain + 5 ms: build/test.out Falcon.Falcon512SamplerZKnownAnswerTests + 5 ms: build/test.out Falcon.Falcon1024SamplerZKnownAnswerTests + 10 ms: build/test.out Falcon.EncodeDecodePublicKey + 13 ms: build/test.out Falcon.NumberTheoreticTransform + 3077 ms: build/test.out Falcon.SignatureCompression + 3227 ms: build/test.out Falcon.KeyGeneration + 3249 ms: build/test.out Falcon.NTRUGen + 3718 ms: build/test.out Falcon.ArithmeticOverZq + 4258 ms: build/test.out Falcon.FastFourierSampling + 4272 ms: build/test.out Falcon.EncodeDecodeSecretKey + 4572 ms: build/test.out Falcon.KeygenSignVerif ``` ## Benchmarking -For benchmarking Falcon{512, 1024} key generation, signing and verification for fixed length message of 32B, issue +For benchmarking Falcon{512, 1024} key generation, signing and verification algorithms, given fixed length message of 32B, issue ```bash -make benchmark +make benchmark -j # If you haven't built google-benchmark library with libPFM support. +make perf -j # If you have built google-benchmark library with libPFM support. ``` -> **Warning** You must disable CPU frequency scaling during benchmarking; see [this](https://github.com/google/benchmark/blob/b111d01c1b4cc86da08672a68cddcbcc1cedd742/docs/user_guide.md#disabling-cpu-frequency-scaling) guide. +> [!CAUTION] +> You must disable CPU frequency scaling during benchmarking; see [this](https://github.com/google/benchmark/blob/b111d01c1b4cc86da08672a68cddcbcc1cedd742/docs/user_guide.md#disabling-cpu-frequency-scaling) guide on how to do that. + +> [!NOTE] +> `make perf -j` - was issued when collecting following benchmarks. Notice, **cycles** column, denoting cost of executing Falcon signature scheme routines in terms of elapsed CPU cycles. Follow [this](https://github.com/google/benchmark/blob/main/docs/perf_counters.md) for more details. + -### On Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz [ Compiled with Clang ] +### On 12th Gen Intel(R) Core(TM) i7-1260P + +Compiled with **gcc version 13.2.0 (Ubuntu 13.2.0-4ubuntu3)**. + +```bash +$ uname -srm +Linux 6.5.0-14-generic x86_64 +``` ```bash -2023-02-18T12:07:57+04:00 -Running ./bench/a.out -Run on (8 X 2400 MHz CPU s) +2024-04-12T12:46:46+04:00 +Running ./build/perf.out +Run on (16 X 4670.99 MHz CPU s) CPU Caches: - L1 Data 32 KiB - L1 Instruction 32 KiB - L2 Unified 256 KiB (x4) - L3 Unified 6144 KiB -Load Average: 2.26, 2.26, 1.98 ----------------------------------------------------------------------------------------------- -Benchmark Time CPU Iterations items_per_second ----------------------------------------------------------------------------------------------- -bench_falcon::keygen<512> 953701 us 952681 us 1 1.04967/s -bench_falcon::sign_single<512>/32 546 us 546 us 1304 1.83235k/s -bench_falcon::sign_many<512>/32 342 us 342 us 2082 2.92446k/s -bench_falcon::verify<512>/32 27.5 us 27.5 us 26034 36.4035k/s -bench_falcon::keygen<1024> 5385395 us 5381617 us 1 0.185818/s -bench_falcon::sign_single<1024>/32 1139 us 1136 us 632 880.013/s -bench_falcon::sign_many<1024>/32 690 us 689 us 1001 1.45054k/s -bench_falcon::verify<1024>/32 55.1 us 55.0 us 12780 18.1959k/s + L1 Data 48 KiB (x8) + L1 Instruction 32 KiB (x8) + L2 Unified 1280 KiB (x8) + L3 Unified 18432 KiB (x1) +Load Average: 1.38, 1.19, 0.94 +--------------------------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations CYCLES items_per_second +--------------------------------------------------------------------------------------------------------- +falcon_sign_single<512>/32_mean 320 us 320 us 16 1.46016M 3.12457k/s +falcon_sign_single<512>/32_median 319 us 319 us 16 1.46034M 3.13373k/s +falcon_sign_single<512>/32_stddev 5.89 us 5.81 us 16 1.77985k 53.8792/s +falcon_sign_single<512>/32_cv 1.84 % 1.81 % 16 0.12% 1.72% +falcon_sign_single<512>/32_min 313 us 313 us 16 1.45564M 2.93297k/s +falcon_sign_single<512>/32_max 341 us 341 us 16 1.46261M 3.19922k/s +falcon_sign_single<1024>/32_mean 650 us 650 us 16 2.97417M 1.53905k/s +falcon_sign_single<1024>/32_median 650 us 650 us 16 2.97525M 1.53914k/s +falcon_sign_single<1024>/32_stddev 3.76 us 3.73 us 16 10.1068k 8.93083/s +falcon_sign_single<1024>/32_cv 0.58 % 0.57 % 16 0.34% 0.58% +falcon_sign_single<1024>/32_min 638 us 638 us 16 2.9391M 1.52263k/s +falcon_sign_single<1024>/32_max 657 us 657 us 16 2.9869M 1.56801k/s +falcon_verify<512>/32_mean 20.3 us 20.3 us 16 93.7515k 49.4226k/s +falcon_verify<512>/32_median 19.8 us 19.8 us 16 92.2862k 50.4788k/s +falcon_verify<512>/32_stddev 1.13 us 1.13 us 16 4.42223k 2.59822k/s +falcon_verify<512>/32_cv 5.58 % 5.58 % 16 4.72% 5.26% +falcon_verify<512>/32_min 19.3 us 19.3 us 16 90.3351k 43.9262k/s +falcon_verify<512>/32_max 22.8 us 22.8 us 16 105.756k 51.8446k/s +falcon_keygen<1024>_mean 2081521 us 2081348 us 16 9.42315G 0.494535/s +falcon_keygen<1024>_median 2123409 us 2123208 us 16 9.49366G 0.470987/s +falcon_keygen<1024>_stddev 285936 us 285905 us 16 1.28563G 0.11184/s +falcon_keygen<1024>_cv 13.74 % 13.74 % 16 13.64% 22.62% +falcon_keygen<1024>_min 1106142 us 1106067 us 16 5.13248G 0.398895/s +falcon_keygen<1024>_max 2507137 us 2506923 us 16 11.619G 0.904104/s +falcon_verify<1024>/32_mean 44.4 us 44.4 us 16 207.814k 22.6869k/s +falcon_verify<1024>/32_median 43.4 us 43.4 us 16 203.196k 23.0538k/s +falcon_verify<1024>/32_stddev 3.99 us 4.00 us 16 18.6401k 1.85145k/s +falcon_verify<1024>/32_cv 9.00 % 9.01 % 16 8.97% 8.16% +falcon_verify<1024>/32_min 39.6 us 39.6 us 16 185.304k 18.2602k/s +falcon_verify<1024>/32_max 54.8 us 54.8 us 16 256.56k 25.2763k/s +falcon_sign_many<512>/32_mean 240 us 240 us 16 1.12495M 4.16211k/s +falcon_sign_many<512>/32_median 240 us 240 us 16 1.12495M 4.1627k/s +falcon_sign_many<512>/32_stddev 0.294 us 0.293 us 16 1.31681k 5.07456/s +falcon_sign_many<512>/32_cv 0.12 % 0.12 % 16 0.12% 0.12% +falcon_sign_many<512>/32_min 240 us 240 us 16 1.123M 4.15473k/s +falcon_sign_many<512>/32_max 241 us 241 us 16 1.12706M 4.16936k/s +falcon_keygen<512>_mean 347534 us 347505 us 16 1.60853G 2.93599/s +falcon_keygen<512>_median 354691 us 354665 us 16 1.62563G 2.8202/s +falcon_keygen<512>_stddev 40624 us 40623 us 16 184.086M 0.53753/s +falcon_keygen<512>_cv 11.69 % 11.69 % 16 11.44% 18.31% +falcon_keygen<512>_min 203496 us 203479 us 16 952.046M 2.60755/s +falcon_keygen<512>_max 383506 us 383502 us 16 1.75497G 4.91452/s +falcon_sign_many<1024>/32_mean 484 us 484 us 16 2.24619M 2.06551k/s +falcon_sign_many<1024>/32_median 484 us 484 us 16 2.24591M 2.06678k/s +falcon_sign_many<1024>/32_stddev 1.26 us 1.26 us 16 4.07933k 5.36503/s +falcon_sign_many<1024>/32_cv 0.26 % 0.26 % 16 0.18% 0.26% +falcon_sign_many<1024>/32_min 482 us 482 us 16 2.24036M 2.05496k/s +falcon_sign_many<1024>/32_max 487 us 487 us 16 2.25521M 2.0733k/s ``` ## Usage @@ -241,13 +295,13 @@ assert(_verified); I strongly advise you to go through following examples demonstrating usage of Falcon key generation/ signing/ verification API. -- [Sign a single message](./example/sign_one.cpp) -- [Sign many messages](./example/sign_many.cpp) +- [Sign a single message](./examples/sign_one.cpp) +- [Sign many messages](./examples/sign_many.cpp) Here's an example showing how to compile and run these examples. ```bash -$ clang++ -std=c++20 -Wall -O3 -march=native -mtune=native -I include/ -I sha3/include/ example/sign_one.cpp -lgmpxx -lgmp && ./a.out +$ clang++ -std=c++20 -Wall -O3 -march=native -mtune=native -I include/ -I sha3/include/ examples/sign_one.cpp -lgmpxx -lgmp && ./a.out Falcon512 (Sign Single Message) From 53790caefd661ee360e143f027837a924e65b7d8 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 12 Apr 2024 13:34:32 +0400 Subject: [PATCH 10/10] update github actions CI yaml script to run tests on multiple targets Signed-off-by: Anjan Roy --- .github/workflows/test_ci.yml | 40 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index 0755220..550a95e 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -1,4 +1,4 @@ -name: Test Falcon using CI +name: Test Falcon Post-Quantum Digital Signature Algorithm on: push: @@ -8,19 +8,31 @@ on: jobs: build: - - runs-on: ubuntu-20.04 + runs-on: ${{matrix.os}} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v3 - - name: Get Dependency - run: git submodule update --init - - name: Setup Compiler + - uses: actions/checkout@v4 + - name: Setup Google-Test run: | - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 9 - sudo apt-get install -y libgmp-dev - - name: Execute Tests - run: make - - name: Cleanup - run: make clean + pushd ~ + git clone https://github.com/google/googletest.git -b v1.14.0 + pushd googletest + mkdir build + pushd build + cmake .. -DBUILD_GMOCK=OFF + make + sudo make install + popd + popd + popd + - name: Install libGMP + run: sudo apt-get install -y libgmp-dev + if: matrix.os == 'ubuntu-latest' + - name: Install libGMP + run: brew install gmp + if: matrix.os == 'macos-latest' + - name: Execute Tests on ${{matrix.os}} + run: make -j