/* * SPDX-License-Identifier: CC0-1.0 * * Copyright (C) 2025 W. Kosior */ #define _POSIX_C_SOURCE 200809L /* for getline() */ #include #include #include #include "pqcrypto_blind_sig.h" static const char sample_message[] = "This is a message to blind-sign."; #define RETRIES_MAX 1000U static void signing_example(blind_sig_ctx_t const ctx) { unsigned long retries_left = RETRIES_MAX; blind_sig_priv_key_t priv_key; blind_sig_pub_key_t pub_key; blind_sig_signer_state_t signer_state; blind_sig_user_state_t user_state; blind_sig_proto_p1_t p1_result; blind_sig_proto_p2_t p2_result; blind_sig_proto_p3_t p3_result; blind_sig_proto_p4_t p4_result; blind_sig_proto_p5_t p5_result; blind_sig_t sig; blind_sig_key_init_gen(priv_key, pub_key, ctx); blind_sig_signer_state_init(signer_state, ctx); blind_sig_user_state_init(user_state, ctx); p1: blind_sig_proto_p1_init_do(p1_result, signer_state, ctx); /* p2: */ blind_sig_proto_p2_init_do(p2_result, user_state, pub_key, sample_message, sizeof(sample_message), p1_result, &retries_left, ctx); if (!p2_result->ok) { blind_sig_proto_p1_clear(p1_result, ctx); blind_sig_proto_p2_clear(p2_result, ctx); goto too_many_retries; } /* p3: */ blind_sig_proto_p3_init_do(p3_result, signer_state, priv_key, p2_result, ctx); if (!p3_result->ok) { blind_sig_proto_p1_clear(p1_result, ctx); blind_sig_proto_p2_clear(p2_result, ctx); blind_sig_proto_p3_clear(p3_result, ctx); if (!(retries_left && retries_left--)) goto too_many_retries; goto p1; } /* p4: */ blind_sig_proto_p4_init_do(p4_result, sig, user_state, p3_result, ctx); /* p5: */ blind_sig_proto_p5_init_do(p5_result, signer_state, pub_key, p4_result, ctx); if (!p5_result->ok) { blind_sig_proto_p1_clear(p1_result, ctx); blind_sig_proto_p2_clear(p2_result, ctx); blind_sig_proto_p3_clear(p3_result, ctx); blind_sig_proto_p4_clear(p4_result, ctx); blind_sig_proto_p5_clear(p5_result, ctx); if (!(retries_left && retries_left--)) goto too_many_retries; goto p1; } /* verification: */ if (!p4_result->needs_restart) { if (blind_sig_verify(sig, pub_key, ctx)) fprintf(stderr, "Signature verified successfully.\n"); else fprintf(stderr, "Signature not valid.\n"); } /* out: */ if (!p4_result->needs_restart) blind_sig_clear(sig, ctx); blind_sig_priv_key_clear(priv_key, ctx); blind_sig_pub_key_clear(pub_key, ctx); blind_sig_signer_state_clear(signer_state, ctx); blind_sig_user_state_clear(user_state, ctx); blind_sig_proto_p1_clear(p1_result, ctx); blind_sig_proto_p2_clear(p2_result, ctx); blind_sig_proto_p3_clear(p3_result, ctx); blind_sig_proto_p4_clear(p4_result, ctx); blind_sig_proto_p5_clear(p5_result, ctx); return; too_many_retries: fprintf(stderr, "Too many retries.\n"); }; static int perform_key_gen(blind_sig_ctx_t ctx) { blind_sig_priv_key_t priv_key; blind_sig_pub_key_t pub_key; blind_sig_key_init_gen(priv_key, pub_key, ctx); blind_sig_priv_key_file_serialize("priv_key.example", priv_key, ctx); blind_sig_pub_key_file_serialize("pub_key.example", pub_key, ctx); blind_sig_priv_key_clear(priv_key, ctx); blind_sig_pub_key_clear(pub_key, ctx); return EXIT_SUCCESS; } static int perform_signing_p1(blind_sig_ctx_t ctx) { blind_sig_signer_state_t signer_state; blind_sig_proto_p1_t p1_result; blind_sig_signer_state_init(signer_state, ctx); blind_sig_proto_p1_init_do(p1_result, signer_state, ctx); blind_sig_signer_state_file_serialize("signer_state.example", signer_state, ctx); blind_sig_proto_p1_file_serialize("p1_result.example", p1_result, ctx); blind_sig_signer_state_clear(signer_state, ctx); blind_sig_proto_p1_clear(p1_result, ctx); return EXIT_SUCCESS; } static int perform_signing_p2(blind_sig_ctx_t ctx) { blind_sig_user_state_t user_state; blind_sig_pub_key_t pub_key; ssize_t message_bytes; char * message_buf = NULL; size_t message_buf_bytes; blind_sig_proto_p1_t p1_result; unsigned long retries_left = RETRIES_MAX; blind_sig_proto_p2_t p2_result; int result = EXIT_SUCCESS; blind_sig_user_state_init(user_state, ctx); blind_sig_pub_key_file_deserialize("pub_key.example", pub_key, ctx); printf("Write a line-one message to blind-sign.\n> "); fflush(stdout); message_bytes = getline(&message_buf, &message_buf_bytes, stdin); if (message_bytes <= 0) abort(); putchar('\n'); blind_sig_proto_p1_file_deserialize("p1_result.example", p1_result, ctx); blind_sig_proto_p2_init_do(p2_result, user_state, pub_key, message_buf, message_bytes, p1_result, &retries_left, ctx); if (!p2_result->ok) { fprintf(stderr, "Too many retries.\n"); result = EXIT_FAILURE; } blind_sig_user_state_file_serialize("user_state.example", user_state, ctx); blind_sig_proto_p2_file_serialize("p2_result.example", p2_result, ctx); blind_sig_user_state_clear(user_state, ctx); blind_sig_pub_key_clear(pub_key, ctx); free(message_buf); blind_sig_proto_p1_clear(p1_result, ctx); blind_sig_proto_p2_clear(p2_result, ctx); return result; } static int perform_signing_p3(blind_sig_ctx_t ctx) { blind_sig_signer_state_t signer_state; blind_sig_priv_key_t priv_key; blind_sig_proto_p2_t p2_result; blind_sig_proto_p3_t p3_result; int result; blind_sig_signer_state_file_deserialize("signer_state.example", signer_state, ctx); blind_sig_priv_key_file_deserialize("priv_key.example", priv_key, ctx); blind_sig_proto_p2_file_deserialize("p2_result.example", p2_result, ctx); blind_sig_proto_p3_init_do(p3_result, signer_state, priv_key, p2_result, ctx); result = p3_result->ok ? EXIT_SUCCESS : EXIT_FAILURE; blind_sig_signer_state_file_serialize("signer_state.example", signer_state, ctx); blind_sig_proto_p3_file_serialize("p3_result.example", p3_result, ctx); blind_sig_signer_state_clear(signer_state, ctx); blind_sig_priv_key_clear(priv_key, ctx); blind_sig_proto_p2_clear(p2_result, ctx); blind_sig_proto_p3_clear(p3_result, ctx); return result; } static int perform_signing_p4(blind_sig_ctx_t ctx) { blind_sig_t sig; blind_sig_user_state_t user_state; blind_sig_proto_p3_t p3_result; blind_sig_proto_p4_t p4_result; int result; blind_sig_user_state_file_deserialize("user_state.example", user_state, ctx); blind_sig_proto_p3_file_deserialize("p3_result.example", p3_result, ctx); blind_sig_proto_p4_init_do(p4_result, sig, user_state, p3_result, ctx); result = p4_result->needs_restart? EXIT_FAILURE : EXIT_SUCCESS; /* No serialization of state — it doesn't get modified here. */ if (!p4_result->needs_restart) blind_sig_file_serialize("sig.example", sig, ctx); blind_sig_proto_p4_file_serialize("p4_result.example", p4_result, ctx); if (!p4_result->needs_restart) blind_sig_clear(sig, ctx); blind_sig_user_state_clear(user_state, ctx); blind_sig_proto_p3_clear(p3_result, ctx); blind_sig_proto_p4_clear(p4_result, ctx); return result; } static int perform_signing_p5(blind_sig_ctx_t ctx) { blind_sig_signer_state_t signer_state; blind_sig_pub_key_t pub_key; blind_sig_proto_p4_t p4_result; blind_sig_proto_p5_t p5_result; int result; blind_sig_signer_state_file_deserialize("signer_state.example", signer_state, ctx); blind_sig_pub_key_file_deserialize("pub_key.example", pub_key, ctx); blind_sig_proto_p4_file_deserialize("p4_result.example", p4_result, ctx); blind_sig_proto_p5_init_do(p5_result, signer_state, pub_key, p4_result, ctx); result = p5_result->ok ? EXIT_SUCCESS : EXIT_FAILURE; /* Again, no serialization of state — it doesn't get modified here. */ blind_sig_proto_p5_file_serialize("p5_result.example", p5_result, ctx); blind_sig_signer_state_clear(signer_state, ctx); blind_sig_pub_key_clear(pub_key, ctx); blind_sig_proto_p4_clear(p4_result, ctx); blind_sig_proto_p5_clear(p5_result, ctx); return result; } static int perform_verification(blind_sig_ctx_t ctx) { blind_sig_t sig; blind_sig_pub_key_t pub_key; int result; blind_sig_file_deserialize("sig.example", sig, ctx); blind_sig_pub_key_file_deserialize("pub_key.example", pub_key, ctx); if (blind_sig_verify(sig, pub_key, ctx)) { fprintf(stderr, "Got valid signature for message.\n"); fwrite(sig->message->buf, sig->message->bytes, 1, stdout); result = EXIT_SUCCESS; } else { fprintf(stderr, "Got invalid signature.\n"); result = EXIT_FAILURE; } blind_sig_clear(sig, ctx); blind_sig_pub_key_clear(pub_key, ctx); return result; } static void perform_example(void) { blind_sig_params_t params; blind_sig_ctx_t ctx; fprintf(stderr, "Preparing blind signature context (\"Current III\" set" " from Rückert's paper).\n"); *params = *blind_sig_params_current_III; params->log_level = BLIND_SIG_LOG_INFO_2_PARAMETERS; /* fprintf(stderr, "Preparing blind signature context (toy set of" */ /* " parameters).\n"); */ /* *params = *blind_sig_params_toy; */ blind_sig_ctx_init(ctx, params); fprintf(stderr, "Making a test signature for ASCII buffer: \"%s\".\n", sample_message); signing_example(ctx); fprintf(stderr, "Done, cleaning up.\n"); blind_sig_ctx_clear(ctx); } int main(const int argc, const char * const * argv) { blind_sig_params_t params; blind_sig_ctx_t ctx; char const * action = argc > 1 ? argv[1] : "example"; int result = EXIT_SUCCESS; if (!strcmp(action, "example")) { perform_example(); goto out; } *params = *blind_sig_params_current_III; params->log_level = BLIND_SIG_LOG_INFO_1_CONTROL; blind_sig_ctx_init(ctx, params); #define X(action_name) \ !strcmp(action, #action_name) ? perform_##action_name(ctx) : result = X(key_gen) X(signing_p1) X(signing_p2) X(signing_p3) X(signing_p4) X(signing_p5) X(verification) (fprintf(stderr, "Bad action `%s'.\n", action), EXIT_FAILURE); #undef X out: flint_cleanup(); return result; }