bitcoin/examples/ecdsa.c
Pieter Wuille 763079a3f1 Squashed 'src/secp256k1/' changes from 21ffe4b22a9..bdf39000b9c
bdf39000b9c Merge bitcoin-core/secp256k1#1223: release: prepare for 0.3.0
b40adf23604 release: prepare for 0.3.0
90b513aadad Merge bitcoin-core/secp256k1#1229: cmake: Rename project to "libsecp256k1"
8be82d43628 cmake: Rename project to "libsecp256k1"
ef4f8bd0259 Merge bitcoin-core/secp256k1#1227: readme: Use correct build type in CMake/Windows build instructions
756b61d451d readme: Use correct build type in CMake/Windows build instructions
3295aa149bd Merge bitcoin-core/secp256k1#1225: changelog: Add entry for CMake
92098d84cf7 changelog: Add entry for CMake
df323b5c146 Merge bitcoin-core/secp256k1#1113: build: Add CMake-based build system
e1eb33724c2 ci: Add "x86_64: Windows (VS 2022)" task
10602b0030e cmake: Export config files
5468d709644 build: Add CMake-based build system
6048e6c03e4 Merge bitcoin-core/secp256k1#1222: Remove redundant checks.
eb8749fcd0f Merge bitcoin-core/secp256k1#1221: Update Changelog
5d8f53e3129 Remove redudent checks.
9d1b458d5fb Merge bitcoin-core/secp256k1#1217: Add secp256k1_fe_add_int function
d232112fa7e Update Changelog
8962fc95bb0 Merge bitcoin-core/secp256k1#1218: Update overflow check
2ef1c9b3870 Update overflow check
57573187826 Merge bitcoin-core/secp256k1#1212: Prevent dead-store elimination when clearing secrets in examples
b081f7e4cbf Add secp256k1_fe_add_int function
5660c137552 prevent optimization in algorithms
09b1d466db7 Merge bitcoin-core/secp256k1#979: Native jacobi symbol algorithm
ce3cfc78a60 doc: Describe Jacobi calculation in safegcd_implementation.md
6be01036c8a Add secp256k1_fe_is_square_var function
1de2a01c2b2 Native jacobi symbol algorithm
04c6c1b1816 Make secp256k1_modinv64_det_check_pow2 support abs val
5fffb2c7af5 Make secp256k1_i128_check_pow2 support -(2^n)
cbd25559343 Merge bitcoin-core/secp256k1#1209: build: Add SECP256K1_API_VAR to fix importing variables from DLLs
1b21aa51752 Merge bitcoin-core/secp256k1#1078: group: Save a normalize_to_zero in gej_add_ge
e4330341bd6 ci: Shutdown wineserver whenever CI script exits
9a5a611a21f build: Suppress stupid MSVC linker warning
739c53b19a2 examples: Extend sig examples by call that uses static context
914276e4d27 build: Add SECP256K1_API_VAR to fix importing variables from DLLs
1cca7c1744b Merge bitcoin-core/secp256k1#1206: build: Add -Wreserved-identifier supported by clang
8c7e0fc1de0 build: Add -Wreserved-identifier supported by clang
8ebe5c52050 Merge bitcoin-core/secp256k1#1201: ci: Do not set git's `user.{email,name}` config options
5596ec5c2cf Merge bitcoin-core/secp256k1#1203: Do not link `bench` and `ctime_tests` to `COMMON_LIB`
ef39721ccce Do not link `bench` and `ctime_tests` to `COMMON_LIB`
9b60e3148d8 ci: Do not set git's `user.{email,name}` config options
e1817a6f54f Merge bitcoin-core/secp256k1#1199: ci: Minor improvements inspired by Bitcoin Core
1bff2005885 Merge bitcoin-core/secp256k1#1200: Drop no longer used Autoheader macros
9b7d18669dc Drop no longer used Autoheader macros
c2415866c7a ci: Don't fetch git history
0ecf3188515 ci: Use remote pull/merge ref instead of local git merge
2b77240b3ba Merge bitcoin-core/secp256k1#1172: benchmarks: fix bench_scalar_split
eb6bebaee39 scalar: restrict split_lambda args, improve doc and VERIFY_CHECKs
7f49aa7f2dc ci: add test job with -DVERIFY
620ba3d74be benchmarks: fix bench_scalar_split
5fbff5d348f Merge bitcoin-core/secp256k1#1170: contexts: Forbid destroying, cloning and randomizing the static context
233822d849d Merge bitcoin-core/secp256k1#1195: ctime_tests: improve output when CHECKMEM_RUNNING is not defined
ad7433b1409 Merge bitcoin-core/secp256k1#1196: Drop no longer used variables from the build system
e39d954f118 tests: Add CHECK_ILLEGAL(_VOID) macros and use in static ctx tests
2cd4e3c0a97 Drop no longer used `SECP_{LIBS,INCLUDE}` variables
613626f94c7 Drop no longer used `SECP_TEST_{LIBS,INCLUDE}` variables
61841fc9ee5 contexts: Forbid randomizing secp256k1_context_static
4b6df5e33e1 contexts: Forbid cloning/destroying secp256k1_context_static
b1579cf5fb4 Merge bitcoin-core/secp256k1#1194: Ensure safety of ctz_debruijn implementation.
8f51229e034 ctime_tests: improve output when CHECKMEM_RUNNING is not defined
d6ff738d5bb Ensure safety of ctz_debruijn implementation.
a01a7d86dc2 Merge bitcoin-core/secp256k1#1192: Switch to exhaustive groups with small B coefficient
a7a7bfaf3dc Merge bitcoin-core/secp256k1#1190: Make all non-API functions (except main) static
f29a3270923 Merge bitcoin-core/secp256k1#1169: Add support for msan instead of valgrind (for memcheck and ctime test)
ff8edf89e2e Merge bitcoin-core/secp256k1#1193: Add `noverify_tests` to `.gitignore`
ce60785b265 Introduce SECP256K1_B macro for curve b coefficient
4934aa79958 Switch to exhaustive groups with small B coefficient
d4a6b58df74 Add `noverify_tests` to `.gitignore`
88e80722d2a Merge bitcoin-core/secp256k1#1160: Makefile: add `-I$(top_srcdir)/{include,src}` to `CPPFLAGS` for precomputed
0f088ec1126 Rename CTIMETEST -> CTIMETESTS
74b026f05d5 Add runtime checking for DECLASSIFY flag
5e2e6fcfc0e Run ctime test in Linux MSan CI job
18974061a3f Make ctime tests building configurable
5048be17e93 Rename valgrind_ctime_test -> ctime_tests
6eed6c18ded Update error messages to suggest msan as well
8e11f89a685 Add support for msan integration to checkmem.h
8dc64079eb1 Add compile-time error to valgrind_ctime_test
0db05a770eb Abstract interactions with valgrind behind new checkmem.h
4f1a54e41d8 Move valgrind CPPFLAGS into SECP_CONFIG_DEFINES
cc3b8a4f404 Merge bitcoin-core/secp256k1#1187: refactor: Rename global variables in tests
9a93f48f502 refactor: Rename STTC to STATIC_CTX in tests
3385a2648d7 refactor: Rename global variables to uppercase in tests
e03ef865593 Make all non-API functions (except main) static
cbe41ac138b Merge bitcoin-core/secp256k1#1188: tests: Add noverify_tests which is like tests but without VERIFY
203760023c6 tests: Add noverify_tests which is like tests but without VERIFY
e862c4af0c5 Makefile: add -I$(top_srcdir)/src to CPPFLAGS for precomputed
0eb3000417f Merge bitcoin-core/secp256k1#1186: tests: Tidy context tests
39e8f0e3d7b refactor: Separate run_context_tests into static vs proper contexts
a4a09379b1a tests: Clean up and improve run_context_tests() further
fc90bb56956 refactor: Tidy up main()
f32a36f620e tests: Don't use global context for context tests
ce4f936c4fa tests: Tidy run_context_tests() by extracting functions
18e0db30cb4 tests: Don't recreate global context in scratch space test
b19806122e9 tests: Use global copy of secp256k1_context_static instead of clone
2a39ac162e0 Merge bitcoin-core/secp256k1#1185: Drop `SECP_CONFIG_DEFINES` from examples
2f9ca284e2a Drop `SECP_CONFIG_DEFINES` from examples
31ed5386e84 Merge bitcoin-core/secp256k1#1183: Bugfix: pass SECP_CONFIG_DEFINES to bench compilation
c0a555b2ae3 Bugfix: pass SECP_CONFIG_DEFINES to bench compilation
01b819a8c7d Merge bitcoin-core/secp256k1#1158: Add a secp256k1_i128_to_u64 function.
eacad90f699 Merge bitcoin-core/secp256k1#1171: Change ARG_CHECK_NO_RETURN to ARG_CHECK_VOID which returns (void)
3f57b9f7749 Merge bitcoin-core/secp256k1#1177: Some improvements to the changelog
c30b889f17e Clarify that the ABI-incompatible versions are earlier
881fc33d0c1 Consistency in naming of modules
665ba77e793 Merge bitcoin-core/secp256k1#1178: Drop `src/libsecp256k1-config.h`
75d7b7f5bae Merge bitcoin-core/secp256k1#1154: ci: set -u in cirrus.sh to treat unset variables as an error
7a746882013 ci: add missing CFLAGS & CPPFLAGS variable to print_environment
c2e0fdadebd ci: set -u in cirrus.sh to treat unset variables as an error
9c5a4d21bbe Do not define unused `HAVE_VALGRIND` macro
ad8647f548c Drop no longer relevant files from `.gitignore`
b627ba7050b Remove dependency on `src/libsecp256k1-config.h`
9ecf8149a19 Reduce font size in changelog
2dc133a67ff Add more changelog entries
ac233e181a5 Add links to diffs to changelog
cee8223ef6d Mention semantic versioning in changelog
9a8d65f07f1 Merge bitcoin-core/secp256k1#1174: release cleanup: bump version after 0.2.0
02ebc290f74 release cleanup: bump version after 0.2.0
b6b360efafc doc: improve message of cleanup commit
a49e0940ad6 docs: Fix typo
2551cdac903 tests: Fix code formatting
c635c1bfd54 Change ARG_CHECK_NO_RETURN to ARG_CHECK_VOID which returns (void)
cf66f2357c6 refactor: Add helper function secp256k1_context_is_proper()
d2164752053 test secp256k1_i128_to_i64
4bc429019dc Add a secp256k1_i128_to_u64 function.
e089eecc1e5 group: Further simply gej_add_ge
ac71020ebe0 group: Save a normalize_to_zero in gej_add_ge

git-subtree-dir: src/secp256k1
git-subtree-split: bdf39000b9c6a0818e7149ccb500873d079e6e85
2023-03-08 17:41:24 -05:00

139 lines
6.1 KiB
C

/*************************************************************************
* Written in 2020-2022 by Elichai Turkel *
* To the extent possible under law, the author(s) have dedicated all *
* copyright and related and neighboring rights to the software in this *
* file to the public domain worldwide. This software is distributed *
* without any warranty. For the CC0 Public Domain Dedication, see *
* EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *
*************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <secp256k1.h>
#include "examples_util.h"
int main(void) {
/* Instead of signing the message directly, we must sign a 32-byte hash.
* Here the message is "Hello, world!" and the hash function was SHA-256.
* An actual implementation should just call SHA-256, but this example
* hardcodes the output to avoid depending on an additional library.
* See https://bitcoin.stackexchange.com/questions/81115/if-someone-wanted-to-pretend-to-be-satoshi-by-posting-a-fake-signature-to-defrau/81116#81116 */
unsigned char msg_hash[32] = {
0x31, 0x5F, 0x5B, 0xDB, 0x76, 0xD0, 0x78, 0xC4,
0x3B, 0x8A, 0xC0, 0x06, 0x4E, 0x4A, 0x01, 0x64,
0x61, 0x2B, 0x1F, 0xCE, 0x77, 0xC8, 0x69, 0x34,
0x5B, 0xFC, 0x94, 0xC7, 0x58, 0x94, 0xED, 0xD3,
};
unsigned char seckey[32];
unsigned char randomize[32];
unsigned char compressed_pubkey[33];
unsigned char serialized_signature[64];
size_t len;
int is_signature_valid, is_signature_valid2;
int return_val;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
/* Before we can call actual API functions, we need to create a "context". */
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
if (!fill_random(randomize, sizeof(randomize))) {
printf("Failed to generate randomness\n");
return 1;
}
/* Randomizing the context is recommended to protect against side-channel
* leakage See `secp256k1_context_randomize` in secp256k1.h for more
* information about it. This should never fail. */
return_val = secp256k1_context_randomize(ctx, randomize);
assert(return_val);
/*** Key Generation ***/
/* If the secret key is zero or out of range (bigger than secp256k1's
* order), we try to sample a new key. Note that the probability of this
* happening is negligible. */
while (1) {
if (!fill_random(seckey, sizeof(seckey))) {
printf("Failed to generate randomness\n");
return 1;
}
if (secp256k1_ec_seckey_verify(ctx, seckey)) {
break;
}
}
/* Public key creation using a valid context with a verified secret key should never fail */
return_val = secp256k1_ec_pubkey_create(ctx, &pubkey, seckey);
assert(return_val);
/* Serialize the pubkey in a compressed form(33 bytes). Should always return 1. */
len = sizeof(compressed_pubkey);
return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey, &len, &pubkey, SECP256K1_EC_COMPRESSED);
assert(return_val);
/* Should be the same size as the size of the output, because we passed a 33 byte array. */
assert(len == sizeof(compressed_pubkey));
/*** Signing ***/
/* Generate an ECDSA signature `noncefp` and `ndata` allows you to pass a
* custom nonce function, passing `NULL` will use the RFC-6979 safe default.
* Signing with a valid context, verified secret key
* and the default nonce function should never fail. */
return_val = secp256k1_ecdsa_sign(ctx, &sig, msg_hash, seckey, NULL, NULL);
assert(return_val);
/* Serialize the signature in a compact form. Should always return 1
* according to the documentation in secp256k1.h. */
return_val = secp256k1_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig);
assert(return_val);
/*** Verification ***/
/* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */
if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) {
printf("Failed parsing the signature\n");
return 1;
}
/* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */
if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) {
printf("Failed parsing the public key\n");
return 1;
}
/* Verify a signature. This will return 1 if it's valid and 0 if it's not. */
is_signature_valid = secp256k1_ecdsa_verify(ctx, &sig, msg_hash, &pubkey);
printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false");
printf("Secret Key: ");
print_hex(seckey, sizeof(seckey));
printf("Public Key: ");
print_hex(compressed_pubkey, sizeof(compressed_pubkey));
printf("Signature: ");
print_hex(serialized_signature, sizeof(serialized_signature));
/* This will clear everything from the context and free the memory */
secp256k1_context_destroy(ctx);
/* Bonus example: if all we need is signature verification (and no key
generation or signing), we don't need to use a context created via
secp256k1_context_create(). We can simply use the static (i.e., global)
context secp256k1_context_static. See its description in
include/secp256k1.h for details. */
is_signature_valid2 = secp256k1_ecdsa_verify(secp256k1_context_static,
&sig, msg_hash, &pubkey);
assert(is_signature_valid2 == is_signature_valid);
/* It's best practice to try to clear secrets from memory after using them.
* This is done because some bugs can allow an attacker to leak memory, for
* example through "out of bounds" array access (see Heartbleed), Or the OS
* swapping them to disk. Hence, we overwrite the secret key buffer with zeros.
*
* Here we are preventing these writes from being optimized out, as any good compiler
* will remove any writes that aren't used. */
secure_erase(seckey, sizeof(seckey));
return 0;
}