mirror of https://github.com/ethereum/go-ethereum
Merge pull request #1853 from Gustav-Simonsson/libsecp256k1_update
Update libsecp256k1, Go wrapper and testspull/1881/head
commit
f466243417
@ -0,0 +1,41 @@ |
||||
bench_inv |
||||
bench_ecdh |
||||
bench_sign |
||||
bench_verify |
||||
bench_schnorr_verify |
||||
bench_recover |
||||
bench_internal |
||||
tests |
||||
gen_context |
||||
*.exe |
||||
*.so |
||||
*.a |
||||
!.gitignore |
||||
|
||||
Makefile |
||||
configure |
||||
.libs/ |
||||
Makefile.in |
||||
aclocal.m4 |
||||
autom4te.cache/ |
||||
config.log |
||||
config.status |
||||
*.tar.gz |
||||
*.la |
||||
libtool |
||||
.deps/ |
||||
.dirstamp |
||||
build-aux/ |
||||
*.lo |
||||
*.o |
||||
*~ |
||||
src/libsecp256k1-config.h |
||||
src/libsecp256k1-config.h.in |
||||
src/ecmult_static_context.h |
||||
m4/libtool.m4 |
||||
m4/ltoptions.m4 |
||||
m4/ltsugar.m4 |
||||
m4/ltversion.m4 |
||||
m4/lt~obsolete.m4 |
||||
src/stamp-h1 |
||||
libsecp256k1.pc |
@ -0,0 +1,62 @@ |
||||
language: c |
||||
sudo: false |
||||
addons: |
||||
apt: |
||||
packages: libgmp-dev |
||||
compiler: |
||||
- clang |
||||
- gcc |
||||
env: |
||||
global: |
||||
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=NO RECOVERY=NO |
||||
matrix: |
||||
- SCALAR=32bit RECOVERY=yes |
||||
- SCALAR=32bit FIELD=32bit ECDH=yes |
||||
- SCALAR=64bit |
||||
- FIELD=64bit RECOVERY=yes |
||||
- FIELD=64bit ENDOMORPHISM=yes |
||||
- FIELD=64bit ENDOMORPHISM=yes ECDH=yes |
||||
- FIELD=64bit ASM=x86_64 |
||||
- FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 |
||||
- FIELD=32bit SCHNORR=yes |
||||
- FIELD=32bit ENDOMORPHISM=yes |
||||
- BIGNUM=no |
||||
- BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes |
||||
- BIGNUM=no STATICPRECOMPUTATION=no |
||||
- BUILD=distcheck |
||||
- EXTRAFLAGS=CFLAGS=-DDETERMINISTIC |
||||
matrix: |
||||
fast_finish: true |
||||
include: |
||||
- compiler: clang |
||||
env: HOST=i686-linux-gnu ENDOMORPHISM=yes |
||||
addons: |
||||
apt: |
||||
packages: |
||||
- gcc-multilib |
||||
- libgmp-dev:i386 |
||||
- compiler: clang |
||||
env: HOST=i686-linux-gnu |
||||
addons: |
||||
apt: |
||||
packages: |
||||
- gcc-multilib |
||||
- compiler: gcc |
||||
env: HOST=i686-linux-gnu ENDOMORPHISM=yes |
||||
addons: |
||||
apt: |
||||
packages: |
||||
- gcc-multilib |
||||
- compiler: gcc |
||||
env: HOST=i686-linux-gnu |
||||
addons: |
||||
apt: |
||||
packages: |
||||
- gcc-multilib |
||||
- libgmp-dev:i386 |
||||
before_script: ./autogen.sh |
||||
script: |
||||
- if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi |
||||
- if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi |
||||
- ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR $EXTRAFLAGS $USE_HOST && make -j2 $BUILD |
||||
os: linux |
@ -0,0 +1,547 @@ |
||||
#ifndef _SECP256K1_ |
||||
# define _SECP256K1_ |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
#include <stddef.h> |
||||
|
||||
/* These rules specify the order of arguments in API calls:
|
||||
* |
||||
* 1. Context pointers go first, followed by output arguments, combined |
||||
* output/input arguments, and finally input-only arguments. |
||||
* 2. Array lengths always immediately the follow the argument whose length |
||||
* they describe, even if this violates rule 1. |
||||
* 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated |
||||
* later go first. This means: signatures, public nonces, private nonces, |
||||
* messages, public keys, secret keys, tweaks. |
||||
* 4. Arguments that are not data pointers go last, from more complex to less |
||||
* complex: function pointers, algorithm names, messages, void pointers, |
||||
* counts, flags, booleans. |
||||
* 5. Opaque data pointers follow the function pointer they are to be passed to. |
||||
*/ |
||||
|
||||
/** Opaque data structure that holds context information (precomputed tables etc.).
|
||||
* |
||||
* The purpose of context structures is to cache large precomputed data tables |
||||
* that are expensive to construct, and also to maintain the randomization data |
||||
* for blinding. |
||||
* |
||||
* Do not create a new context object for each operation, as construction is |
||||
* far slower than all other API calls (~100 times slower than an ECDSA |
||||
* verification). |
||||
* |
||||
* A constructed context can safely be used from multiple threads |
||||
* simultaneously, but API call that take a non-const pointer to a context |
||||
* need exclusive access to it. In particular this is the case for |
||||
* secp256k1_context_destroy and secp256k1_context_randomize. |
||||
* |
||||
* Regarding randomization, either do it once at creation time (in which case |
||||
* you do not need any locking for the other calls), or use a read-write lock. |
||||
*/ |
||||
typedef struct secp256k1_context_struct secp256k1_context; |
||||
|
||||
/** Opaque data structure that holds a parsed and valid public key.
|
||||
* |
||||
* The exact representation of data inside is implementation defined and not |
||||
* guaranteed to be portable between different platforms or versions. It is |
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved. |
||||
* If you need to convert to a format suitable for storage or transmission, use |
||||
* secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. |
||||
* |
||||
* Furthermore, it is guaranteed that identical public keys (ignoring |
||||
* compression) will have identical representation, so they can be memcmp'ed. |
||||
*/ |
||||
typedef struct { |
||||
unsigned char data[64]; |
||||
} secp256k1_pubkey; |
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature.
|
||||
* |
||||
* The exact representation of data inside is implementation defined and not |
||||
* guaranteed to be portable between different platforms or versions. It is |
||||
* however guaranteed to be 64 bytes in size, and can be safely copied/moved. |
||||
* If you need to convert to a format suitable for storage or transmission, use |
||||
* the secp256k1_ecdsa_signature_serialize_* and |
||||
* secp256k1_ecdsa_signature_serialize_* functions. |
||||
* |
||||
* Furthermore, it is guaranteed to identical signatures will have identical |
||||
* representation, so they can be memcmp'ed. |
||||
*/ |
||||
typedef struct { |
||||
unsigned char data[64]; |
||||
} secp256k1_ecdsa_signature; |
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
* |
||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. |
||||
* Out: nonce32: pointer to a 32-byte array to be filled by the function. |
||||
* In: msg32: the 32-byte message hash being verified (will not be NULL) |
||||
* key32: pointer to a 32-byte secret key (will not be NULL) |
||||
* algo16: pointer to a 16-byte array describing the signature |
||||
* algorithm (will be NULL for ECDSA for compatibility). |
||||
* data: Arbitrary data pointer that is passed through. |
||||
* attempt: how many iterations we have tried to find a nonce. |
||||
* This will almost always be 0, but different attempt values |
||||
* are required to result in a different nonce. |
||||
* |
||||
* Except for test cases, this function should compute some cryptographic hash of |
||||
* the message, the algorithm, the key and the attempt. |
||||
*/ |
||||
typedef int (*secp256k1_nonce_function)( |
||||
unsigned char *nonce32, |
||||
const unsigned char *msg32, |
||||
const unsigned char *key32, |
||||
const unsigned char *algo16, |
||||
void *data, |
||||
unsigned int attempt |
||||
); |
||||
|
||||
# if !defined(SECP256K1_GNUC_PREREQ) |
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__) |
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) \ |
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) |
||||
# else |
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 |
||||
# endif |
||||
# endif |
||||
|
||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) |
||||
# if SECP256K1_GNUC_PREREQ(2,7) |
||||
# define SECP256K1_INLINE __inline__ |
||||
# elif (defined(_MSC_VER)) |
||||
# define SECP256K1_INLINE __inline |
||||
# else |
||||
# define SECP256K1_INLINE |
||||
# endif |
||||
# else |
||||
# define SECP256K1_INLINE inline |
||||
# endif |
||||
|
||||
#ifndef SECP256K1_API |
||||
# if defined(_WIN32) |
||||
# ifdef SECP256K1_BUILD |
||||
# define SECP256K1_API __declspec(dllexport) |
||||
# else |
||||
# define SECP256K1_API |
||||
# endif |
||||
# elif defined(__GNUC__) && defined(SECP256K1_BUILD) |
||||
# define SECP256K1_API __attribute__ ((visibility ("default"))) |
||||
# else |
||||
# define SECP256K1_API |
||||
# endif |
||||
#endif |
||||
|
||||
/**Warning attributes
|
||||
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out |
||||
* some paranoid null checks. */ |
||||
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) |
||||
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) |
||||
# else |
||||
# define SECP256K1_WARN_UNUSED_RESULT |
||||
# endif |
||||
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) |
||||
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) |
||||
# else |
||||
# define SECP256K1_ARG_NONNULL(_x) |
||||
# endif |
||||
|
||||
/** Flags to pass to secp256k1_context_create. */ |
||||
# define SECP256K1_CONTEXT_VERIFY (1 << 0) |
||||
# define SECP256K1_CONTEXT_SIGN (1 << 1) |
||||
|
||||
/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ |
||||
# define SECP256K1_EC_COMPRESSED (1 << 0) |
||||
|
||||
/** Create a secp256k1 context object.
|
||||
* |
||||
* Returns: a newly created context object. |
||||
* In: flags: which parts of the context to initialize. |
||||
*/ |
||||
SECP256K1_API secp256k1_context* secp256k1_context_create( |
||||
unsigned int flags |
||||
) SECP256K1_WARN_UNUSED_RESULT; |
||||
|
||||
/** Copies a secp256k1 context object.
|
||||
* |
||||
* Returns: a newly created context object. |
||||
* Args: ctx: an existing context to copy (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API secp256k1_context* secp256k1_context_clone( |
||||
const secp256k1_context* ctx |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; |
||||
|
||||
/** Destroy a secp256k1 context object.
|
||||
* |
||||
* The context pointer may not be used afterwards. |
||||
* Args: ctx: an existing context to destroy (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API void secp256k1_context_destroy( |
||||
secp256k1_context* ctx |
||||
); |
||||
|
||||
/** Set a callback function to be called when an illegal argument is passed to
|
||||
* an API call. It will only trigger for violations that are mentioned |
||||
* explicitly in the header. |
||||
* |
||||
* The philosophy is that these shouldn't be dealt with through a |
||||
* specific return value, as calling code should not have branches to deal with |
||||
* the case that this code itself is broken. |
||||
* |
||||
* On the other hand, during debug stage, one would want to be informed about |
||||
* such mistakes, and the default (crashing) may be inadvisable. |
||||
* When this callback is triggered, the API function called is guaranteed not |
||||
* to cause a crash, though its return value and output arguments are |
||||
* undefined. |
||||
* |
||||
* Args: ctx: an existing context object (cannot be NULL) |
||||
* In: fun: a pointer to a function to call when an illegal argument is |
||||
* passed to the API, taking a message and an opaque pointer |
||||
* (NULL restores a default handler that calls abort). |
||||
* data: the opaque pointer to pass to fun above. |
||||
*/ |
||||
SECP256K1_API void secp256k1_context_set_illegal_callback( |
||||
secp256k1_context* ctx, |
||||
void (*fun)(const char* message, void* data), |
||||
const void* data |
||||
) SECP256K1_ARG_NONNULL(1); |
||||
|
||||
/** Set a callback function to be called when an internal consistency check
|
||||
* fails. The default is crashing. |
||||
* |
||||
* This can only trigger in case of a hardware failure, miscompilation, |
||||
* memory corruption, serious bug in the library, or other error would can |
||||
* otherwise result in undefined behaviour. It will not trigger due to mere |
||||
* incorrect usage of the API (see secp256k1_context_set_illegal_callback |
||||
* for that). After this callback returns, anything may happen, including |
||||
* crashing. |
||||
* |
||||
* Args: ctx: an existing context object (cannot be NULL) |
||||
* In: fun: a pointer to a function to call when an interal error occurs, |
||||
* taking a message and an opaque pointer (NULL restores a default |
||||
* handler that calls abort). |
||||
* data: the opaque pointer to pass to fun above. |
||||
*/ |
||||
SECP256K1_API void secp256k1_context_set_error_callback( |
||||
secp256k1_context* ctx, |
||||
void (*fun)(const char* message, void* data), |
||||
const void* data |
||||
) SECP256K1_ARG_NONNULL(1); |
||||
|
||||
/** Parse a variable-length public key into the pubkey object.
|
||||
* |
||||
* Returns: 1 if the public key was fully valid. |
||||
* 0 if the public key could not be parsed or is invalid. |
||||
* Args: ctx: a secp256k1 context object. |
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a |
||||
* parsed version of input. If not, its value is undefined. |
||||
* In: input: pointer to a serialized public key |
||||
* inputlen: length of the array pointed to by input |
||||
* |
||||
* This function supports parsing compressed (33 bytes, header byte 0x02 or |
||||
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header |
||||
* byte 0x06 or 0x07) format public keys. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey* pubkey, |
||||
const unsigned char *input, |
||||
size_t inputlen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Serialize a pubkey object into a serialized byte sequence.
|
||||
* |
||||
* Returns: 1 always. |
||||
* Args: ctx: a secp256k1 context object. |
||||
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if |
||||
* compressed==1) byte array to place the serialized key in. |
||||
* outputlen: a pointer to an integer which will contain the serialized |
||||
* size. |
||||
* In: pubkey: a pointer to a secp256k1_pubkey containing an initialized |
||||
* public key. |
||||
* flags: SECP256K1_EC_COMPRESSED if serialization should be in |
||||
* compressed format. |
||||
*/ |
||||
SECP256K1_API int secp256k1_ec_pubkey_serialize( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *output, |
||||
size_t *outputlen, |
||||
const secp256k1_pubkey* pubkey, |
||||
unsigned int flags |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Parse a DER ECDSA signature.
|
||||
* |
||||
* Returns: 1 when the signature could be parsed, 0 otherwise. |
||||
* Args: ctx: a secp256k1 context object |
||||
* Out: sig: a pointer to a signature object |
||||
* In: input: a pointer to the signature to be parsed |
||||
* inputlen: the length of the array pointed to be input |
||||
* |
||||
* Note that this function also supports some violations of DER and even BER. |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_signature_parse_der( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_signature* sig, |
||||
const unsigned char *input, |
||||
size_t inputlen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Serialize an ECDSA signature in DER format.
|
||||
* |
||||
* Returns: 1 if enough space was available to serialize, 0 otherwise |
||||
* Args: ctx: a secp256k1 context object |
||||
* Out: output: a pointer to an array to store the DER serialization |
||||
* In/Out: outputlen: a pointer to a length integer. Initially, this integer |
||||
* should be set to the length of output. After the call |
||||
* it will be set to the length of the serialization (even |
||||
* if 0 was returned). |
||||
* In: sig: a pointer to an initialized signature object |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *output, |
||||
size_t *outputlen, |
||||
const secp256k1_ecdsa_signature* sig |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Verify an ECDSA signature.
|
||||
* |
||||
* Returns: 1: correct signature |
||||
* 0: incorrect or unparseable signature |
||||
* Args: ctx: a secp256k1 context object, initialized for verification. |
||||
* In: sig: the signature being verified (cannot be NULL) |
||||
* msg32: the 32-byte message hash being verified (cannot be NULL) |
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( |
||||
const secp256k1_context* ctx, |
||||
const secp256k1_ecdsa_signature *sig, |
||||
const unsigned char *msg32, |
||||
const secp256k1_pubkey *pubkey |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
|
||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of |
||||
* extra entropy. |
||||
*/ |
||||
extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; |
||||
|
||||
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ |
||||
extern const secp256k1_nonce_function secp256k1_nonce_function_default; |
||||
|
||||
/** Create an ECDSA signature.
|
||||
* |
||||
* Returns: 1: signature created |
||||
* 0: the nonce generation function failed, or the private key was invalid. |
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) |
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL) |
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL) |
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used |
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) |
||||
* |
||||
* The sig always has an s value in the lower half of the range (From 0x1 |
||||
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, |
||||
* inclusive), unlike many other implementations. |
||||
* |
||||
* With ECDSA a third-party can can forge a second distinct signature |
||||
* of the same message given a single initial signature without knowing |
||||
* the key by setting s to its additive inverse mod-order, 'flipping' the |
||||
* sign of the random point R which is not included in the signature. |
||||
* Since the forgery is of the same message this isn't universally |
||||
* problematic, but in systems where message malleability or uniqueness |
||||
* of signatures is important this can cause issues. This forgery can be |
||||
* blocked by all verifiers forcing signers to use a canonical form. The |
||||
* lower-S form reduces the size of signatures slightly on average when |
||||
* variable length encodings (such as DER) are used and is cheap to |
||||
* verify, making it a good choice. Security of always using lower-S is |
||||
* assured because anyone can trivially modify a signature after the |
||||
* fact to enforce this property. Adjusting it inside the signing |
||||
* function avoids the need to re-serialize or have curve specific |
||||
* constants outside of the library. By always using a canonical form |
||||
* even in applications where it isn't needed it becomes possible to |
||||
* impose a requirement later if a need is discovered. |
||||
* No other forms of ECDSA malleability are known and none seem likely, |
||||
* but there is no formal proof that ECDSA, even with this additional |
||||
* restriction, is free of other malleability. Commonly used serialization |
||||
* schemes will also accept various non-unique encodings, so care should |
||||
* be taken when this property is required for an application. |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_sign( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_signature *sig, |
||||
const unsigned char *msg32, |
||||
const unsigned char *seckey, |
||||
secp256k1_nonce_function noncefp, |
||||
const void *ndata |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Verify an ECDSA secret key.
|
||||
* |
||||
* Returns: 1: secret key is valid |
||||
* 0: secret key is invalid |
||||
* Args: ctx: pointer to a context object (cannot be NULL) |
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( |
||||
const secp256k1_context* ctx, |
||||
const unsigned char *seckey |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); |
||||
|
||||
/** Compute the public key for a secret key.
|
||||
* |
||||
* Returns: 1: secret was valid, public key stores |
||||
* 0: secret was invalid, try again |
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) |
||||
* Out: pubkey: pointer to the created public key (cannot be NULL) |
||||
* In: seckey: pointer to a 32-byte private key (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubkey, |
||||
const unsigned char *seckey |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Export a private key in BER format.
|
||||
* |
||||
* Returns: 1 if the private key was valid. |
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot |
||||
* be NULL) |
||||
* Out: privkey: pointer to an array for storing the private key in BER. |
||||
* Should have space for 279 bytes, and cannot be NULL. |
||||
* privkeylen: Pointer to an int where the length of the private key in |
||||
* privkey will be stored. |
||||
* In: seckey: pointer to a 32-byte secret key to export. |
||||
* flags: SECP256K1_EC_COMPRESSED if the key should be exported in |
||||
* compressed format. |
||||
* |
||||
* This function is purely meant for compatibility with applications that |
||||
* require BER encoded keys. When working with secp256k1-specific code, the |
||||
* simple 32-byte private keys are sufficient. |
||||
* |
||||
* Note that this function does not guarantee correct DER output. It is |
||||
* guaranteed to be parsable by secp256k1_ec_privkey_import. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *privkey, |
||||
size_t *privkeylen, |
||||
const unsigned char *seckey, |
||||
unsigned int flags |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Import a private key in DER format.
|
||||
* Returns: 1 if a private key was extracted. |
||||
* Args: ctx: pointer to a context object (cannot be NULL). |
||||
* Out: seckey: pointer to a 32-byte array for storing the private key. |
||||
* (cannot be NULL). |
||||
* In: privkey: pointer to a private key in DER format (cannot be NULL). |
||||
* privkeylen: length of the DER private key pointed to be privkey. |
||||
* |
||||
* This function will accept more than just strict DER, and even allow some BER |
||||
* violations. The public key stored inside the DER-encoded private key is not |
||||
* verified for correctness, nor are the curve parameters. Use this function |
||||
* only if you know in advance it is supposed to contain a secp256k1 private |
||||
* key. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *seckey, |
||||
const unsigned char *privkey, |
||||
size_t privkeylen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Tweak a private key by adding tweak to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for |
||||
* uniformly random 32-byte arrays, or if the resulting private key |
||||
* would be invalid (only when the tweak is the complement of the |
||||
* private key). 1 otherwise. |
||||
* Args: ctx: pointer to a context object (cannot be NULL). |
||||
* In/Out: seckey: pointer to a 32-byte private key. |
||||
* In: tweak: pointer to a 32-byte tweak. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *seckey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Tweak a public key by adding tweak times the generator to it.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for |
||||
* uniformly random 32-byte arrays, or if the resulting public key |
||||
* would be invalid (only when the tweak is the complement of the |
||||
* corresponding private key). 1 otherwise. |
||||
* Args: ctx: pointer to a context object initialized for validation |
||||
* (cannot be NULL). |
||||
* In/Out: pubkey: pointer to a public key object. |
||||
* In: tweak: pointer to a 32-byte tweak. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubkey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Tweak a private key by multiplying it by a tweak.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for |
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise. |
||||
* Args: ctx: pointer to a context object (cannot be NULL). |
||||
* In/Out: seckey: pointer to a 32-byte private key. |
||||
* In: tweak: pointer to a 32-byte tweak. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *seckey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Tweak a public key by multiplying it by a tweak value.
|
||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for |
||||
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise. |
||||
* Args: ctx: pointer to a context object initialized for validation |
||||
* (cannot be NULL). |
||||
* In/Out: pubkey: pointer to a public key obkect. |
||||
* In: tweak: pointer to a 32-byte tweak. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubkey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Updates the context randomization.
|
||||
* Returns: 1: randomization successfully updated |
||||
* 0: error |
||||
* Args: ctx: pointer to a context object (cannot be NULL) |
||||
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( |
||||
secp256k1_context* ctx, |
||||
const unsigned char *seed32 |
||||
) SECP256K1_ARG_NONNULL(1); |
||||
|
||||
/** Add a number of public keys together.
|
||||
* Returns: 1: the sum of the public keys is valid. |
||||
* 0: the sum of the public keys is not valid. |
||||
* Args: ctx: pointer to a context object |
||||
* Out: out: pointer to pubkey for placing the resulting public key |
||||
* (cannot be NULL) |
||||
* In: ins: pointer to array of pointers to public keys (cannot be NULL) |
||||
* n: the number of public keys to add together (must be at least 1) |
||||
* Use secp256k1_ec_pubkey_compress and secp256k1_ec_pubkey_decompress if the |
||||
* uncompressed format is needed. |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *out, |
||||
const secp256k1_pubkey * const * ins, |
||||
int n |
||||
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
|
||||
#endif |
@ -0,0 +1,30 @@ |
||||
#ifndef _SECP256K1_ECDH_ |
||||
# define _SECP256K1_ECDH_ |
||||
|
||||
# include "secp256k1.h" |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
/** Compute an EC Diffie-Hellman secret in constant time
|
||||
* Returns: 1: exponentiation was successful |
||||
* 0: scalar was invalid (zero or overflow) |
||||
* Args: ctx: pointer to a context object (cannot be NULL) |
||||
* Out: result: a 32-byte array which will be populated by an ECDH |
||||
* secret computed from the point and scalar |
||||
* In: point: pointer to a public point |
||||
* scalar: a 32-byte scalar with which to multiply the point |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *result, |
||||
const secp256k1_pubkey *point, |
||||
const unsigned char *scalar |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
|
||||
#endif |
@ -0,0 +1,110 @@ |
||||
#ifndef _SECP256K1_RECOVERY_ |
||||
# define _SECP256K1_RECOVERY_ |
||||
|
||||
# include "secp256k1.h" |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
/** Opaque data structured that holds a parsed ECDSA signature,
|
||||
* supporting pubkey recovery. |
||||
* |
||||
* The exact representation of data inside is implementation defined and not |
||||
* guaranteed to be portable between different platforms or versions. It is |
||||
* however guaranteed to be 65 bytes in size, and can be safely copied/moved. |
||||
* If you need to convert to a format suitable for storage or transmission, use |
||||
* the secp256k1_ecdsa_signature_serialize_* and |
||||
* secp256k1_ecdsa_signature_parse_* functions. |
||||
* |
||||
* Furthermore, it is guaranteed that identical signatures (including their |
||||
* recoverability) will have identical representation, so they can be |
||||
* memcmp'ed. |
||||
*/ |
||||
typedef struct { |
||||
unsigned char data[65]; |
||||
} secp256k1_ecdsa_recoverable_signature; |
||||
|
||||
/** Parse a compact ECDSA signature (64 bytes + recovery id).
|
||||
* |
||||
* Returns: 1 when the signature could be parsed, 0 otherwise |
||||
* Args: ctx: a secp256k1 context object |
||||
* Out: sig: a pointer to a signature object |
||||
* In: input64: a pointer to a 64-byte compact signature |
||||
* recid: the recovery id (0, 1, 2 or 3) |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_recoverable_signature* sig, |
||||
const unsigned char *input64, |
||||
int recid |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Convert a recoverable signature into a normal signature.
|
||||
* |
||||
* Returns: 1 |
||||
* Out: sig: a pointer to a normal signature (cannot be NULL). |
||||
* In: sigin: a pointer to a recoverable signature (cannot be NULL). |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_signature* sig, |
||||
const secp256k1_ecdsa_recoverable_signature* sigin |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
|
||||
* |
||||
* Returns: 1 |
||||
* Args: ctx: a secp256k1 context object |
||||
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) |
||||
* recid: a pointer to an integer to hold the recovery id (can be NULL). |
||||
* In: sig: a pointer to an initialized signature object (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *output64, |
||||
int *recid, |
||||
const secp256k1_ecdsa_recoverable_signature* sig |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Create a recoverable ECDSA signature.
|
||||
* |
||||
* Returns: 1: signature created |
||||
* 0: the nonce generation function failed, or the private key was invalid. |
||||
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) |
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL) |
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL) |
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used |
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) |
||||
*/ |
||||
SECP256K1_API int secp256k1_ecdsa_sign_recoverable( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_ecdsa_recoverable_signature *sig, |
||||
const unsigned char *msg32, |
||||
const unsigned char *seckey, |
||||
secp256k1_nonce_function noncefp, |
||||
const void *ndata |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Recover an ECDSA public key from a signature.
|
||||
* |
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature). |
||||
* 0: otherwise. |
||||
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) |
||||
* Out: pubkey: pointer to the recoved public key (cannot be NULL) |
||||
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) |
||||
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubkey, |
||||
const secp256k1_ecdsa_recoverable_signature *sig, |
||||
const unsigned char *msg32 |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
|
||||
#endif |
@ -0,0 +1,173 @@ |
||||
#ifndef _SECP256K1_SCHNORR_ |
||||
# define _SECP256K1_SCHNORR_ |
||||
|
||||
# include "secp256k1.h" |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
/** Create a signature using a custom EC-Schnorr-SHA256 construction. It
|
||||
* produces non-malleable 64-byte signatures which support public key recovery |
||||
* batch validation, and multiparty signing. |
||||
* Returns: 1: signature created |
||||
* 0: the nonce generation function failed, or the private key was |
||||
* invalid. |
||||
* Args: ctx: pointer to a context object, initialized for signing |
||||
* (cannot be NULL) |
||||
* Out: sig64: pointer to a 64-byte array where the signature will be |
||||
* placed (cannot be NULL) |
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL) |
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
* noncefp:pointer to a nonce generation function. If NULL, |
||||
* secp256k1_nonce_function_default is used |
||||
* ndata: pointer to arbitrary data used by the nonce generation |
||||
* function (can be NULL) |
||||
*/ |
||||
SECP256K1_API int secp256k1_schnorr_sign( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *sig64, |
||||
const unsigned char *msg32, |
||||
const unsigned char *seckey, |
||||
secp256k1_nonce_function noncefp, |
||||
const void *ndata |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Verify a signature created by secp256k1_schnorr_sign.
|
||||
* Returns: 1: correct signature |
||||
* 0: incorrect signature |
||||
* Args: ctx: a secp256k1 context object, initialized for verification. |
||||
* In: sig64: the 64-byte signature being verified (cannot be NULL) |
||||
* msg32: the 32-byte message hash being verified (cannot be NULL) |
||||
* pubkey: the public key to verify with (cannot be NULL) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify( |
||||
const secp256k1_context* ctx, |
||||
const unsigned char *sig64, |
||||
const unsigned char *msg32, |
||||
const secp256k1_pubkey *pubkey |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Recover an EC public key from a Schnorr signature created using
|
||||
* secp256k1_schnorr_sign. |
||||
* Returns: 1: public key successfully recovered (which guarantees a correct |
||||
* signature). |
||||
* 0: otherwise. |
||||
* Args: ctx: pointer to a context object, initialized for |
||||
* verification (cannot be NULL) |
||||
* Out: pubkey: pointer to a pubkey to set to the recovered public key |
||||
* (cannot be NULL). |
||||
* In: sig64: signature as 64 byte array (cannot be NULL) |
||||
* msg32: the 32-byte message hash assumed to be signed (cannot |
||||
* be NULL) |
||||
*/ |
||||
SECP256K1_API int secp256k1_schnorr_recover( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubkey, |
||||
const unsigned char *sig64, |
||||
const unsigned char *msg32 |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Generate a nonce pair deterministically for use with
|
||||
* secp256k1_schnorr_partial_sign. |
||||
* Returns: 1: valid nonce pair was generated. |
||||
* 0: otherwise (nonce generation function failed) |
||||
* Args: ctx: pointer to a context object, initialized for signing |
||||
* (cannot be NULL) |
||||
* Out: pubnonce: public side of the nonce (cannot be NULL) |
||||
* privnonce32: private side of the nonce (32 byte) (cannot be NULL) |
||||
* In: msg32: the 32-byte message hash assumed to be signed (cannot |
||||
* be NULL) |
||||
* sec32: the 32-byte private key (cannot be NULL) |
||||
* noncefp: pointer to a nonce generation function. If NULL, |
||||
* secp256k1_nonce_function_default is used |
||||
* noncedata: pointer to arbitrary data used by the nonce generation |
||||
* function (can be NULL) |
||||
* |
||||
* Do not use the output as a private/public key pair for signing/validation. |
||||
*/ |
||||
SECP256K1_API int secp256k1_schnorr_generate_nonce_pair( |
||||
const secp256k1_context* ctx, |
||||
secp256k1_pubkey *pubnonce, |
||||
unsigned char *privnonce32, |
||||
const unsigned char *msg32, |
||||
const unsigned char *sec32, |
||||
secp256k1_nonce_function noncefp, |
||||
const void* noncedata |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Produce a partial Schnorr signature, which can be combined using
|
||||
* secp256k1_schnorr_partial_combine, to end up with a full signature that is |
||||
* verifiable using secp256k1_schnorr_verify. |
||||
* Returns: 1: signature created succesfully. |
||||
* 0: no valid signature exists with this combination of keys, nonces |
||||
* and message (chance around 1 in 2^128) |
||||
* -1: invalid private key, nonce, or public nonces. |
||||
* Args: ctx: pointer to context object, initialized for signing (cannot |
||||
* be NULL) |
||||
* Out: sig64: pointer to 64-byte array to put partial signature in |
||||
* In: msg32: pointer to 32-byte message to sign |
||||
* sec32: pointer to 32-byte private key |
||||
* pubnonce_others: pointer to pubkey containing the sum of the other's |
||||
* nonces (see secp256k1_ec_pubkey_combine) |
||||
* secnonce32: pointer to 32-byte array containing our nonce |
||||
* |
||||
* The intended procedure for creating a multiparty signature is: |
||||
* - Each signer S[i] with private key x[i] and public key Q[i] runs |
||||
* secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of |
||||
* private/public nonces. |
||||
* - All signers communicate their public nonces to each other (revealing your |
||||
* private nonce can lead to discovery of your private key, so it should be |
||||
* considered secret). |
||||
* - All signers combine all the public nonces they received (excluding their |
||||
* own) using secp256k1_ec_pubkey_combine to obtain an |
||||
* Rall[i] = sum(R[0..i-1,i+1..n]). |
||||
* - All signers produce a partial signature using |
||||
* secp256k1_schnorr_partial_sign, passing in their own private key x[i], |
||||
* their own private nonce k[i], and the sum of the others' public nonces |
||||
* Rall[i]. |
||||
* - All signers communicate their partial signatures to each other. |
||||
* - Someone combines all partial signatures using |
||||
* secp256k1_schnorr_partial_combine, to obtain a full signature. |
||||
* - The resulting signature is validatable using secp256k1_schnorr_verify, with |
||||
* public key equal to the result of secp256k1_ec_pubkey_combine of the |
||||
* signers' public keys (sum(Q[0..n])). |
||||
* |
||||
* Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine |
||||
* function take their arguments in any order, and it is possible to |
||||
* pre-combine several inputs already with one call, and add more inputs later |
||||
* by calling the function again (they are commutative and associative). |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *sig64, |
||||
const unsigned char *msg32, |
||||
const unsigned char *sec32, |
||||
const secp256k1_pubkey *pubnonce_others, |
||||
const unsigned char *secnonce32 |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); |
||||
|
||||
/** Combine multiple Schnorr partial signatures.
|
||||
* Returns: 1: the passed signatures were succesfully combined. |
||||
* 0: the resulting signature is not valid (chance of 1 in 2^256) |
||||
* -1: some inputs were invalid, or the signatures were not created |
||||
* using the same set of nonces |
||||
* Args: ctx: pointer to a context object |
||||
* Out: sig64: pointer to a 64-byte array to place the combined signature |
||||
* (cannot be NULL) |
||||
* In: sig64sin: pointer to an array of n pointers to 64-byte input |
||||
* signatures |
||||
* n: the number of signatures to combine (at least 1) |
||||
*/ |
||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine( |
||||
const secp256k1_context* ctx, |
||||
unsigned char *sig64, |
||||
const unsigned char * const * sig64sin, |
||||
int n |
||||
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
|
||||
#endif |
@ -0,0 +1,32 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_BASIC_CONFIG_ |
||||
#define _SECP256K1_BASIC_CONFIG_ |
||||
|
||||
#ifdef USE_BASIC_CONFIG |
||||
|
||||
#undef USE_ASM_X86_64 |
||||
#undef USE_ENDOMORPHISM |
||||
#undef USE_FIELD_10X26 |
||||
#undef USE_FIELD_5X52 |
||||
#undef USE_FIELD_INV_BUILTIN |
||||
#undef USE_FIELD_INV_NUM |
||||
#undef USE_NUM_GMP |
||||
#undef USE_NUM_NONE |
||||
#undef USE_SCALAR_4X64 |
||||
#undef USE_SCALAR_8X32 |
||||
#undef USE_SCALAR_INV_BUILTIN |
||||
#undef USE_SCALAR_INV_NUM |
||||
|
||||
#define USE_NUM_NONE 1 |
||||
#define USE_FIELD_INV_BUILTIN 1 |
||||
#define USE_SCALAR_INV_BUILTIN 1 |
||||
#define USE_FIELD_10X26 1 |
||||
#define USE_SCALAR_8X32 1 |
||||
|
||||
#endif // USE_BASIC_CONFIG
|
||||
#endif // _SECP256K1_BASIC_CONFIG_
|
@ -0,0 +1,53 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "include/secp256k1.h" |
||||
#include "include/secp256k1_ecdh.h" |
||||
#include "util.h" |
||||
#include "bench.h" |
||||
|
||||
typedef struct { |
||||
secp256k1_context *ctx; |
||||
secp256k1_pubkey point; |
||||
unsigned char scalar[32]; |
||||
} bench_ecdh_t; |
||||
|
||||
static void bench_ecdh_setup(void* arg) { |
||||
int i; |
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg; |
||||
const unsigned char point[] = { |
||||
0x03, |
||||
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, |
||||
0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, |
||||
0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, |
||||
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f |
||||
}; |
||||
|
||||
data->ctx = secp256k1_context_create(0); |
||||
for (i = 0; i < 32; i++) { |
||||
data->scalar[i] = i + 1; |
||||
} |
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); |
||||
} |
||||
|
||||
static void bench_ecdh(void* arg) { |
||||
int i; |
||||
unsigned char res[32]; |
||||
bench_ecdh_t *data = (bench_ecdh_t*)arg; |
||||
|
||||
for (i = 0; i < 20000; i++) { |
||||
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); |
||||
} |
||||
} |
||||
|
||||
int main(void) { |
||||
bench_ecdh_t data; |
||||
|
||||
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); |
||||
return 0; |
||||
} |
@ -0,0 +1,73 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "include/secp256k1.h" |
||||
#include "include/secp256k1_schnorr.h" |
||||
#include "util.h" |
||||
#include "bench.h" |
||||
|
||||
typedef struct { |
||||
unsigned char key[32]; |
||||
unsigned char sig[64]; |
||||
unsigned char pubkey[33]; |
||||
size_t pubkeylen; |
||||
} benchmark_schnorr_sig_t; |
||||
|
||||
typedef struct { |
||||
secp256k1_context *ctx; |
||||
unsigned char msg[32]; |
||||
benchmark_schnorr_sig_t sigs[64]; |
||||
int numsigs; |
||||
} benchmark_schnorr_verify_t; |
||||
|
||||
static void benchmark_schnorr_init(void* arg) { |
||||
int i, k; |
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; |
||||
|
||||
for (i = 0; i < 32; i++) { |
||||
data->msg[i] = 1 + i; |
||||
} |
||||
for (k = 0; k < data->numsigs; k++) { |
||||
secp256k1_pubkey pubkey; |
||||
for (i = 0; i < 32; i++) { |
||||
data->sigs[k].key[i] = 33 + i + k; |
||||
} |
||||
secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); |
||||
data->sigs[k].pubkeylen = 33; |
||||
CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); |
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); |
||||
} |
||||
} |
||||
|
||||
static void benchmark_schnorr_verify(void* arg) { |
||||
int i; |
||||
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; |
||||
|
||||
for (i = 0; i < 20000 / data->numsigs; i++) { |
||||
secp256k1_pubkey pubkey; |
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); |
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); |
||||
CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); |
||||
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
int main(void) { |
||||
benchmark_schnorr_verify_t data; |
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); |
||||
|
||||
data.numsigs = 1; |
||||
run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); |
||||
|
||||
secp256k1_context_destroy(data.ctx); |
||||
return 0; |
||||
} |
@ -0,0 +1,22 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECDSA_ |
||||
#define _SECP256K1_ECDSA_ |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
#include "ecmult.h" |
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); |
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); |
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); |
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); |
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid); |
||||
|
||||
#endif |
@ -0,0 +1,28 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECKEY_ |
||||
#define _SECP256K1_ECKEY_ |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#include "group.h" |
||||
#include "scalar.h" |
||||
#include "ecmult.h" |
||||
#include "ecmult_gen.h" |
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); |
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, unsigned int flags); |
||||
|
||||
static int secp256k1_eckey_privkey_parse(secp256k1_scalar *key, const unsigned char *privkey, size_t privkeylen); |
||||
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar *key, unsigned int flags); |
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); |
||||
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); |
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); |
||||
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); |
||||
|
||||
#endif |
@ -0,0 +1,31 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_ |
||||
#define _SECP256K1_ECMULT_ |
||||
|
||||
#include "num.h" |
||||
#include "group.h" |
||||
|
||||
typedef struct { |
||||
/* For accelerating the computation of a*P + b*G: */ |
||||
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ |
||||
#endif |
||||
} secp256k1_ecmult_context; |
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); |
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); |
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, |
||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb); |
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); |
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); |
||||
|
||||
/** Double multiply: R = na*A + ng*G */ |
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); |
||||
|
||||
#endif |
@ -1,19 +1,15 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Copyright (c) 2015 Andrew Poelstra * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_ |
||||
#define _SECP256K1_ECMULT_GEN_ |
||||
#ifndef _SECP256K1_ECMULT_CONST_ |
||||
#define _SECP256K1_ECMULT_CONST_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
|
||||
static void secp256k1_ecmult_gen_start(void); |
||||
static void secp256k1_ecmult_gen_stop(void); |
||||
|
||||
/** Multiply with the generator: R = a*G */ |
||||
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *a); |
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); |
||||
|
||||
#endif |
@ -0,0 +1,260 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_CONST_IMPL_ |
||||
#define _SECP256K1_ECMULT_CONST_IMPL_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
#include "ecmult_const.h" |
||||
#include "ecmult_impl.h" |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
#define WNAF_BITS 128 |
||||
#else |
||||
#define WNAF_BITS 256 |
||||
#endif |
||||
#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) |
||||
|
||||
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ |
||||
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ |
||||
int m; \
|
||||
int abs_n = (n) * (((n) > 0) * 2 - 1); \
|
||||
int idx_n = abs_n / 2; \
|
||||
secp256k1_fe neg_y; \
|
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \
|
||||
VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \
|
||||
for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \
|
||||
/* This loop is used to avoid secret data in array indices. See
|
||||
* the comment in ecmult_gen_impl.h for rationale. */ \
|
||||
secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \
|
||||
secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \
|
||||
} \
|
||||
(r)->infinity = 0; \
|
||||
secp256k1_fe_negate(&neg_y, &(r)->y, 1); \
|
||||
secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \
|
||||
} while(0) |
||||
|
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val)
|
||||
* with the following guarantees: |
||||
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w) |
||||
* - each wnaf[i] is nonzero |
||||
* - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w |
||||
* |
||||
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar |
||||
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) |
||||
* CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 |
||||
* |
||||
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 |
||||
*/ |
||||
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { |
||||
int global_sign; |
||||
int skew = 0; |
||||
int word = 0; |
||||
/* 1 2 3 */ |
||||
int u_last; |
||||
int u; |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
int flip; |
||||
int bit; |
||||
secp256k1_scalar neg_s; |
||||
int not_neg_one; |
||||
/* If we are using the endomorphism, we cannot handle even numbers by negating
|
||||
* them, since we are working with 128-bit numbers whose negations would be 256 |
||||
* bits, eliminating the performance advantage. Instead we use a technique from |
||||
* Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) |
||||
* or 2 (for odd) to the number we are encoding, then compensating after the |
||||
* multiplication. */ |
||||
/* Negative 128-bit numbers will be negated, since otherwise they are 256-bit */ |
||||
flip = secp256k1_scalar_is_high(&s); |
||||
/* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ |
||||
bit = flip ^ (s.d[0] & 1); |
||||
/* We check for negative one, since adding 2 to it will cause an overflow */ |
||||
secp256k1_scalar_negate(&neg_s, &s); |
||||
not_neg_one = !secp256k1_scalar_is_one(&neg_s); |
||||
secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); |
||||
/* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
|
||||
* that we added two to it and flipped it. In fact for -1 these operations are |
||||
* identical. We only flipped, but since skewing is required (in the sense that |
||||
* the skew must be 1 or 2, never zero) and flipping is not, we need to change |
||||
* our flags to claim that we only skewed. */ |
||||
global_sign = secp256k1_scalar_cond_negate(&s, flip); |
||||
global_sign *= not_neg_one * 2 - 1; |
||||
skew = 1 << bit; |
||||
#else |
||||
/* Otherwise, we just negate to force oddness */ |
||||
int is_even = secp256k1_scalar_is_even(&s); |
||||
global_sign = secp256k1_scalar_cond_negate(&s, is_even); |
||||
#endif |
||||
|
||||
/* 4 */ |
||||
u_last = secp256k1_scalar_shr_int(&s, w); |
||||
while (word * w < WNAF_BITS) { |
||||
int sign; |
||||
int even; |
||||
|
||||
/* 4.1 4.4 */ |
||||
u = secp256k1_scalar_shr_int(&s, w); |
||||
/* 4.2 */ |
||||
even = ((u & 1) == 0); |
||||
sign = 2 * (u_last > 0) - 1; |
||||
u += sign * even; |
||||
u_last -= sign * even * (1 << w); |
||||
|
||||
/* 4.3, adapted for global sign change */ |
||||
wnaf[word++] = u_last * global_sign; |
||||
|
||||
u_last = u; |
||||
} |
||||
wnaf[word] = u * global_sign; |
||||
|
||||
VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); |
||||
VERIFY_CHECK(word == WNAF_SIZE(w)); |
||||
return skew; |
||||
} |
||||
|
||||
|
||||
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { |
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_ge tmpa; |
||||
secp256k1_fe Z; |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; |
||||
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; |
||||
int skew_1; |
||||
int skew_lam; |
||||
secp256k1_scalar q_1, q_lam; |
||||
#else |
||||
int wnaf[1 + WNAF_SIZE(WINDOW_A - 1)]; |
||||
#endif |
||||
|
||||
int i; |
||||
secp256k1_scalar sc = *scalar; |
||||
|
||||
/* build wnaf representation for q. */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ |
||||
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); |
||||
/* no need for zero correction when using endomorphism since even
|
||||
* numbers have one added to them anyway */ |
||||
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); |
||||
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); |
||||
#else |
||||
int is_zero = secp256k1_scalar_is_zero(scalar); |
||||
/* the wNAF ladder cannot handle zero, so bump this to one .. we will
|
||||
* correct the result after the fact */ |
||||
sc.d[0] += is_zero; |
||||
VERIFY_CHECK(!secp256k1_scalar_is_zero(&sc)); |
||||
|
||||
secp256k1_wnaf_const(wnaf, sc, WINDOW_A - 1); |
||||
#endif |
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored |
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending |
||||
* that the Z coordinate was 1, use affine addition formulae, and correct |
||||
* the Z coordinate of the result once at the end. |
||||
*/ |
||||
secp256k1_gej_set_ge(r, a); |
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); |
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { |
||||
secp256k1_fe_normalize_weak(&pre_a[i].y); |
||||
} |
||||
#ifdef USE_ENDOMORPHISM |
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { |
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); |
||||
} |
||||
#endif |
||||
|
||||
/* first loop iteration (separated out so we can directly set r, rather
|
||||
* than having it start at infinity, get doubled several times, then have |
||||
* its new value added to it) */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; |
||||
VERIFY_CHECK(i != 0); |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); |
||||
secp256k1_gej_set_ge(r, &tmpa); |
||||
|
||||
i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; |
||||
VERIFY_CHECK(i != 0); |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); |
||||
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
#else |
||||
i = wnaf[WNAF_SIZE(WINDOW_A - 1)]; |
||||
VERIFY_CHECK(i != 0); |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); |
||||
secp256k1_gej_set_ge(r, &tmpa); |
||||
#endif |
||||
/* remaining loop iterations */ |
||||
for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { |
||||
int n; |
||||
int j; |
||||
for (j = 0; j < WINDOW_A - 1; ++j) { |
||||
secp256k1_gej_double_nonzero(r, r, NULL); |
||||
} |
||||
#ifdef USE_ENDOMORPHISM |
||||
n = wnaf_1[i]; |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); |
||||
VERIFY_CHECK(n != 0); |
||||
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
|
||||
n = wnaf_lam[i]; |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); |
||||
VERIFY_CHECK(n != 0); |
||||
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
#else |
||||
n = wnaf[i]; |
||||
VERIFY_CHECK(n != 0); |
||||
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); |
||||
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
#endif |
||||
} |
||||
|
||||
secp256k1_fe_mul(&r->z, &r->z, &Z); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
{ |
||||
/* Correct for wNAF skew */ |
||||
secp256k1_ge correction = *a; |
||||
secp256k1_ge_storage correction_1_stor; |
||||
secp256k1_ge_storage correction_lam_stor; |
||||
secp256k1_ge_storage a2_stor; |
||||
secp256k1_gej tmpj; |
||||
secp256k1_gej_set_ge(&tmpj, &correction); |
||||
secp256k1_gej_double_var(&tmpj, &tmpj, NULL); |
||||
secp256k1_ge_set_gej(&correction, &tmpj); |
||||
secp256k1_ge_to_storage(&correction_1_stor, a); |
||||
secp256k1_ge_to_storage(&correction_lam_stor, a); |
||||
secp256k1_ge_to_storage(&a2_stor, &correction); |
||||
|
||||
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ |
||||
secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); |
||||
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); |
||||
|
||||
/* Apply the correction */ |
||||
secp256k1_ge_from_storage(&correction, &correction_1_stor); |
||||
secp256k1_ge_neg(&correction, &correction); |
||||
secp256k1_gej_add_ge(r, r, &correction); |
||||
|
||||
secp256k1_ge_from_storage(&correction, &correction_lam_stor); |
||||
secp256k1_ge_neg(&correction, &correction); |
||||
secp256k1_ge_mul_lambda(&correction, &correction); |
||||
secp256k1_gej_add_ge(r, r, &correction); |
||||
} |
||||
#else |
||||
/* correct for zero */ |
||||
r->infinity |= is_zero; |
||||
#endif |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,43 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_ |
||||
#define _SECP256K1_ECMULT_GEN_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
|
||||
typedef struct { |
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism: |
||||
* * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. |
||||
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: |
||||
* * U_i = U * 2^i (for i=0..62) |
||||
* * U_i = U * (1-2^63) (for i=63) |
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. |
||||
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is |
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). |
||||
* None of the resulting prec group elements have a known scalar, and neither do any of |
||||
* the intermediate sums while computing a*G. |
||||
*/ |
||||
secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ |
||||
secp256k1_scalar blind; |
||||
secp256k1_gej initial; |
||||
} secp256k1_ecmult_gen_context; |
||||
|
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); |
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); |
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, |
||||
const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); |
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); |
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); |
||||
|
||||
/** Multiply with the generator: R = a*G */ |
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); |
||||
|
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); |
||||
|
||||
#endif |
@ -0,0 +1,205 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ |
||||
#define _SECP256K1_ECMULT_GEN_IMPL_H_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
#include "ecmult_gen.h" |
||||
#include "hash_impl.h" |
||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION |
||||
#include "ecmult_static_context.h" |
||||
#endif |
||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { |
||||
ctx->prec = NULL; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) { |
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION |
||||
secp256k1_ge prec[1024]; |
||||
secp256k1_gej gj; |
||||
secp256k1_gej nums_gej; |
||||
int i, j; |
||||
#endif |
||||
|
||||
if (ctx->prec != NULL) { |
||||
return; |
||||
} |
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION |
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); |
||||
|
||||
/* get the generator */ |
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); |
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ |
||||
{ |
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; |
||||
secp256k1_fe nums_x; |
||||
secp256k1_ge nums_ge; |
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32)); |
||||
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0)); |
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge); |
||||
/* Add G to make the bits in x uniformly distributed. */ |
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); |
||||
} |
||||
|
||||
/* compute prec. */ |
||||
{ |
||||
secp256k1_gej precj[1024]; /* Jacobian versions of prec. */ |
||||
secp256k1_gej gbase; |
||||
secp256k1_gej numsbase; |
||||
gbase = gj; /* 16^j * G */ |
||||
numsbase = nums_gej; /* 2^j * nums. */ |
||||
for (j = 0; j < 64; j++) { |
||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ |
||||
precj[j*16] = numsbase; |
||||
for (i = 1; i < 16; i++) { |
||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); |
||||
} |
||||
/* Multiply gbase by 16. */ |
||||
for (i = 0; i < 4; i++) { |
||||
secp256k1_gej_double_var(&gbase, &gbase, NULL); |
||||
} |
||||
/* Multiply numbase by 2. */ |
||||
secp256k1_gej_double_var(&numsbase, &numsbase, NULL); |
||||
if (j == 62) { |
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ |
||||
secp256k1_gej_neg(&numsbase, &numsbase); |
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); |
||||
} |
||||
} |
||||
secp256k1_ge_set_all_gej_var(1024, prec, precj, cb); |
||||
} |
||||
for (j = 0; j < 64; j++) { |
||||
for (i = 0; i < 16; i++) { |
||||
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); |
||||
} |
||||
} |
||||
#else |
||||
(void)cb; |
||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context; |
||||
#endif |
||||
secp256k1_ecmult_gen_blind(ctx, NULL); |
||||
} |
||||
|
||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { |
||||
return ctx->prec != NULL; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, |
||||
const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { |
||||
if (src->prec == NULL) { |
||||
dst->prec = NULL; |
||||
} else { |
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION |
||||
dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); |
||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec)); |
||||
#else |
||||
(void)cb; |
||||
dst->prec = src->prec; |
||||
#endif |
||||
dst->initial = src->initial; |
||||
dst->blind = src->blind; |
||||
} |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { |
||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION |
||||
free(ctx->prec); |
||||
#endif |
||||
secp256k1_scalar_clear(&ctx->blind); |
||||
secp256k1_gej_clear(&ctx->initial); |
||||
ctx->prec = NULL; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { |
||||
secp256k1_ge add; |
||||
secp256k1_ge_storage adds; |
||||
secp256k1_scalar gnb; |
||||
int bits; |
||||
int i, j; |
||||
memset(&adds, 0, sizeof(adds)); |
||||
*r = ctx->initial; |
||||
/* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ |
||||
secp256k1_scalar_add(&gnb, gn, &ctx->blind); |
||||
add.infinity = 0; |
||||
for (j = 0; j < 64; j++) { |
||||
bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); |
||||
for (i = 0; i < 16; i++) { |
||||
/** This uses a conditional move to avoid any secret data in array indexes.
|
||||
* _Any_ use of secret indexes has been demonstrated to result in timing |
||||
* sidechannels, even when the cache-line access patterns are uniform. |
||||
* See also: |
||||
* "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe |
||||
* (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and
|
||||
* "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, |
||||
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer |
||||
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
|
||||
*/ |
||||
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); |
||||
} |
||||
secp256k1_ge_from_storage(&add, &adds); |
||||
secp256k1_gej_add_ge(r, r, &add); |
||||
} |
||||
bits = 0; |
||||
secp256k1_ge_clear(&add); |
||||
secp256k1_scalar_clear(&gnb); |
||||
} |
||||
|
||||
/* Setup blinding values for secp256k1_ecmult_gen. */ |
||||
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { |
||||
secp256k1_scalar b; |
||||
secp256k1_gej gb; |
||||
secp256k1_fe s; |
||||
unsigned char nonce32[32]; |
||||
secp256k1_rfc6979_hmac_sha256_t rng; |
||||
int retry; |
||||
unsigned char keydata[64] = {0}; |
||||
if (seed32 == NULL) { |
||||
/* When seed is NULL, reset the initial point and blinding value. */ |
||||
secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); |
||||
secp256k1_gej_neg(&ctx->initial, &ctx->initial); |
||||
secp256k1_scalar_set_int(&ctx->blind, 1); |
||||
} |
||||
/* The prior blinding value (if not reset) is chained forward by including it in the hash. */ |
||||
secp256k1_scalar_get_b32(nonce32, &ctx->blind); |
||||
/** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data,
|
||||
* and guards against weak or adversarial seeds. This is a simpler and safer interface than |
||||
* asking the caller for blinding values directly and expecting them to retry on failure. |
||||
*/ |
||||
memcpy(keydata, nonce32, 32); |
||||
if (seed32 != NULL) { |
||||
memcpy(keydata + 32, seed32, 32); |
||||
} |
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); |
||||
memset(keydata, 0, sizeof(keydata)); |
||||
/* Retry for out of range results to achieve uniformity. */ |
||||
do { |
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
||||
retry = !secp256k1_fe_set_b32(&s, nonce32); |
||||
retry |= secp256k1_fe_is_zero(&s); |
||||
} while (retry); |
||||
/* Randomize the projection to defend against multiplier sidechannels. */ |
||||
secp256k1_gej_rescale(&ctx->initial, &s); |
||||
secp256k1_fe_clear(&s); |
||||
do { |
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
||||
secp256k1_scalar_set_b32(&b, nonce32, &retry); |
||||
/* A blinding value of 0 works, but would undermine the projection hardening. */ |
||||
retry |= secp256k1_scalar_is_zero(&b); |
||||
} while (retry); |
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng); |
||||
memset(nonce32, 0, 32); |
||||
secp256k1_ecmult_gen(ctx, &gb, &b); |
||||
secp256k1_scalar_negate(&b, &b); |
||||
ctx->blind = b; |
||||
ctx->initial = gb; |
||||
secp256k1_scalar_clear(&b); |
||||
secp256k1_gej_clear(&gb); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,389 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_IMPL_H_ |
||||
#define _SECP256K1_ECMULT_IMPL_H_ |
||||
|
||||
#include "group.h" |
||||
#include "scalar.h" |
||||
#include "ecmult.h" |
||||
|
||||
/* optimal for 128-bit and 256-bit exponents. */ |
||||
#define WINDOW_A 5 |
||||
|
||||
/** larger numbers may result in slightly better performance, at the cost of
|
||||
exponentially larger precomputed tables. */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Two tables for window size 15: 1.375 MiB. */ |
||||
#define WINDOW_G 15 |
||||
#else |
||||
/** One table for window size 16: 1.375 MiB. */ |
||||
#define WINDOW_G 16 |
||||
#endif |
||||
|
||||
/** The number of entries a table with precomputed multiples needs to have. */ |
||||
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) |
||||
|
||||
/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain
|
||||
* the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will |
||||
* contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. |
||||
* Prej's Z values are undefined, except for the last value. |
||||
*/ |
||||
static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { |
||||
secp256k1_gej d; |
||||
secp256k1_ge a_ge, d_ge; |
||||
int i; |
||||
|
||||
VERIFY_CHECK(!a->infinity); |
||||
|
||||
secp256k1_gej_double_var(&d, a, NULL); |
||||
|
||||
/*
|
||||
* Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate |
||||
* of 'd', and scale the 1P starting value's x/y coordinates without changing its z. |
||||
*/ |
||||
d_ge.x = d.x; |
||||
d_ge.y = d.y; |
||||
d_ge.infinity = 0; |
||||
|
||||
secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); |
||||
prej[0].x = a_ge.x; |
||||
prej[0].y = a_ge.y; |
||||
prej[0].z = a->z; |
||||
prej[0].infinity = 0; |
||||
|
||||
zr[0] = d.z; |
||||
for (i = 1; i < n; i++) { |
||||
secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); |
||||
} |
||||
|
||||
/*
|
||||
* Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only |
||||
* the final point's z coordinate is actually used though, so just update that. |
||||
*/ |
||||
secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); |
||||
} |
||||
|
||||
/** Fill a table 'pre' with precomputed odd multiples of a.
|
||||
* |
||||
* There are two versions of this function: |
||||
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its |
||||
* resulting point set to a single constant Z denominator, stores the X and Y |
||||
* coordinates as ge_storage points in pre, and stores the global Z in rz. |
||||
* It only operates on tables sized for WINDOW_A wnaf multiples. |
||||
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its |
||||
* resulting point set to actually affine points, and stores those in pre. |
||||
* It operates on tables of any size, but uses heap-allocated temporaries. |
||||
* |
||||
* To compute a*P + b*G, we compute a table for P using the first function, |
||||
* and for G using the second (which requires an inverse, but it only needs to |
||||
* happen once). |
||||
*/ |
||||
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { |
||||
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
|
||||
/* Compute the odd multiples in Jacobian form. */ |
||||
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); |
||||
/* Bring them to the same Z denominator. */ |
||||
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); |
||||
} |
||||
|
||||
static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { |
||||
secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); |
||||
secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); |
||||
secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); |
||||
int i; |
||||
|
||||
/* Compute the odd multiples in Jacobian form. */ |
||||
secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); |
||||
/* Convert them in batch to affine coordinates. */ |
||||
secp256k1_ge_set_table_gej_var(n, prea, prej, zr); |
||||
/* Convert them to compact storage form. */ |
||||
for (i = 0; i < n; i++) { |
||||
secp256k1_ge_to_storage(&pre[i], &prea[i]); |
||||
} |
||||
|
||||
free(prea); |
||||
free(prej); |
||||
free(zr); |
||||
} |
||||
|
||||
/** The following two macro retrieves a particular odd multiple from a table
|
||||
* of precomputed multiples. */ |
||||
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ |
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
*(r) = (pre)[((n)-1)/2]; \
|
||||
} else { \
|
||||
secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \
|
||||
} \
|
||||
} while(0) |
||||
|
||||
#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ |
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
|
||||
} else { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
|
||||
secp256k1_ge_neg((r), (r)); \
|
||||
} \
|
||||
} while(0) |
||||
|
||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { |
||||
ctx->pre_g = NULL; |
||||
#ifdef USE_ENDOMORPHISM |
||||
ctx->pre_g_128 = NULL; |
||||
#endif |
||||
} |
||||
|
||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { |
||||
secp256k1_gej gj; |
||||
|
||||
if (ctx->pre_g != NULL) { |
||||
return; |
||||
} |
||||
|
||||
/* get the generator */ |
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); |
||||
|
||||
ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); |
||||
|
||||
/* precompute the tables with odd multiples */ |
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
{ |
||||
secp256k1_gej g_128j; |
||||
int i; |
||||
|
||||
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); |
||||
|
||||
/* calculate 2^128*generator */ |
||||
g_128j = gj; |
||||
for (i = 0; i < 128; i++) { |
||||
secp256k1_gej_double_var(&g_128j, &g_128j, NULL); |
||||
} |
||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, |
||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { |
||||
if (src->pre_g == NULL) { |
||||
dst->pre_g = NULL; |
||||
} else { |
||||
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); |
||||
dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); |
||||
memcpy(dst->pre_g, src->pre_g, size); |
||||
} |
||||
#ifdef USE_ENDOMORPHISM |
||||
if (src->pre_g_128 == NULL) { |
||||
dst->pre_g_128 = NULL; |
||||
} else { |
||||
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); |
||||
dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); |
||||
memcpy(dst->pre_g_128, src->pre_g_128, size); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { |
||||
return ctx->pre_g != NULL; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { |
||||
free(ctx->pre_g); |
||||
#ifdef USE_ENDOMORPHISM |
||||
free(ctx->pre_g_128); |
||||
#endif |
||||
secp256k1_ecmult_context_init(ctx); |
||||
} |
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
|
||||
* with the following guarantees: |
||||
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) |
||||
* - two non-zero entries in wnaf are separated by at least w-1 zeroes. |
||||
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more |
||||
* than the number of bits in the (absolute value) of the input. |
||||
*/ |
||||
static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { |
||||
secp256k1_scalar s = *a; |
||||
int last_set_bit = -1; |
||||
int bit = 0; |
||||
int sign = 1; |
||||
int carry = 0; |
||||
|
||||
VERIFY_CHECK(wnaf != NULL); |
||||
VERIFY_CHECK(0 <= len && len <= 256); |
||||
VERIFY_CHECK(a != NULL); |
||||
VERIFY_CHECK(2 <= w && w <= 31); |
||||
|
||||
memset(wnaf, 0, len * sizeof(wnaf[0])); |
||||
|
||||
if (secp256k1_scalar_get_bits(&s, 255, 1)) { |
||||
secp256k1_scalar_negate(&s, &s); |
||||
sign = -1; |
||||
} |
||||
|
||||
while (bit < len) { |
||||
int now; |
||||
int word; |
||||
if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { |
||||
bit++; |
||||
continue; |
||||
} |
||||
|
||||
now = w; |
||||
if (now > len - bit) { |
||||
now = len - bit; |
||||
} |
||||
|
||||
word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; |
||||
|
||||
carry = (word >> (w-1)) & 1; |
||||
word -= carry << w; |
||||
|
||||
wnaf[bit] = sign * word; |
||||
last_set_bit = bit; |
||||
|
||||
bit += now; |
||||
} |
||||
#ifdef VERIFY |
||||
CHECK(carry == 0); |
||||
while (bit < 256) { |
||||
CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); |
||||
}
|
||||
#endif |
||||
return last_set_bit + 1; |
||||
} |
||||
|
||||
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { |
||||
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_ge tmpa; |
||||
secp256k1_fe Z; |
||||
#ifdef USE_ENDOMORPHISM |
||||
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_scalar na_1, na_lam; |
||||
/* Splitted G factors. */ |
||||
secp256k1_scalar ng_1, ng_128; |
||||
int wnaf_na_1[130]; |
||||
int wnaf_na_lam[130]; |
||||
int bits_na_1; |
||||
int bits_na_lam; |
||||
int wnaf_ng_1[129]; |
||||
int bits_ng_1; |
||||
int wnaf_ng_128[129]; |
||||
int bits_ng_128; |
||||
#else |
||||
int wnaf_na[256]; |
||||
int bits_na; |
||||
int wnaf_ng[256]; |
||||
int bits_ng; |
||||
#endif |
||||
int i; |
||||
int bits; |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ |
||||
secp256k1_scalar_split_lambda(&na_1, &na_lam, na); |
||||
|
||||
/* build wnaf representation for na_1 and na_lam. */ |
||||
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); |
||||
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); |
||||
VERIFY_CHECK(bits_na_1 <= 130); |
||||
VERIFY_CHECK(bits_na_lam <= 130); |
||||
bits = bits_na_1; |
||||
if (bits_na_lam > bits) { |
||||
bits = bits_na_lam; |
||||
} |
||||
#else |
||||
/* build wnaf representation for na. */ |
||||
bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); |
||||
bits = bits_na; |
||||
#endif |
||||
|
||||
/* Calculate odd multiples of a.
|
||||
* All multiples are brought to the same Z 'denominator', which is stored |
||||
* in Z. Due to secp256k1' isomorphism we can do all operations pretending |
||||
* that the Z coordinate was 1, use affine addition formulae, and correct |
||||
* the Z coordinate of the result once at the end. |
||||
* The exception is the precomputed G table points, which are actually |
||||
* affine. Compared to the base used for other points, they have a Z ratio |
||||
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same |
||||
* isomorphism to efficiently add with a known Z inverse. |
||||
*/ |
||||
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { |
||||
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); |
||||
} |
||||
|
||||
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ |
||||
secp256k1_scalar_split_128(&ng_1, &ng_128, ng); |
||||
|
||||
/* Build wnaf representation for ng_1 and ng_128 */ |
||||
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); |
||||
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); |
||||
if (bits_ng_1 > bits) { |
||||
bits = bits_ng_1; |
||||
} |
||||
if (bits_ng_128 > bits) { |
||||
bits = bits_ng_128; |
||||
} |
||||
#else |
||||
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); |
||||
if (bits_ng > bits) { |
||||
bits = bits_ng; |
||||
} |
||||
#endif |
||||
|
||||
secp256k1_gej_set_infinity(r); |
||||
|
||||
for (i = bits - 1; i >= 0; i--) { |
||||
int n; |
||||
secp256k1_gej_double_var(r, r, NULL); |
||||
#ifdef USE_ENDOMORPHISM |
||||
if (i < bits_na_1 && (n = wnaf_na_1[i])) { |
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); |
||||
} |
||||
if (i < bits_na_lam && (n = wnaf_na_lam[i])) { |
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); |
||||
} |
||||
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); |
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); |
||||
} |
||||
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); |
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); |
||||
} |
||||
#else |
||||
if (i < bits_na && (n = wnaf_na[i])) { |
||||
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); |
||||
} |
||||
if (i < bits_ng && (n = wnaf_ng[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); |
||||
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
if (!r->infinity) { |
||||
secp256k1_fe_mul(&r->z, &r->z, &Z); |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,74 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#define USE_BASIC_CONFIG 1 |
||||
|
||||
#include "basic-config.h" |
||||
#include "include/secp256k1.h" |
||||
#include "field_impl.h" |
||||
#include "scalar_impl.h" |
||||
#include "group_impl.h" |
||||
#include "ecmult_gen_impl.h" |
||||
|
||||
static void default_error_callback_fn(const char* str, void* data) { |
||||
(void)data; |
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); |
||||
abort(); |
||||
} |
||||
|
||||
static const secp256k1_callback default_error_callback = { |
||||
default_error_callback_fn, |
||||
NULL |
||||
}; |
||||
|
||||
int main(int argc, char **argv) { |
||||
secp256k1_ecmult_gen_context ctx; |
||||
int inner; |
||||
int outer; |
||||
FILE* fp; |
||||
|
||||
(void)argc; |
||||
(void)argv; |
||||
|
||||
fp = fopen("src/ecmult_static_context.h","w"); |
||||
if (fp == NULL) { |
||||
fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); |
||||
return -1; |
||||
} |
||||
|
||||
fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); |
||||
fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); |
||||
fprintf(fp, "#include \"group.h\"\n"); |
||||
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); |
||||
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); |
||||
|
||||
secp256k1_ecmult_gen_context_init(&ctx); |
||||
secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); |
||||
for(outer = 0; outer != 64; outer++) { |
||||
fprintf(fp,"{\n"); |
||||
for(inner = 0; inner != 16; inner++) { |
||||
fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); |
||||
if (inner != 15) { |
||||
fprintf(fp,",\n"); |
||||
} else { |
||||
fprintf(fp,"\n"); |
||||
} |
||||
} |
||||
if (outer != 63) { |
||||
fprintf(fp,"},\n"); |
||||
} else { |
||||
fprintf(fp,"}\n"); |
||||
} |
||||
} |
||||
fprintf(fp,"};\n"); |
||||
secp256k1_ecmult_gen_context_clear(&ctx); |
||||
|
||||
fprintf(fp, "#undef SC\n"); |
||||
fprintf(fp, "#endif\n"); |
||||
fclose(fp); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,141 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_GROUP_ |
||||
#define _SECP256K1_GROUP_ |
||||
|
||||
#include "num.h" |
||||
#include "field.h" |
||||
|
||||
/** A group element of the secp256k1 curve, in affine coordinates. */ |
||||
typedef struct { |
||||
secp256k1_fe x; |
||||
secp256k1_fe y; |
||||
int infinity; /* whether this represents the point at infinity */ |
||||
} secp256k1_ge; |
||||
|
||||
#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} |
||||
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} |
||||
|
||||
/** A group element of the secp256k1 curve, in jacobian coordinates. */ |
||||
typedef struct { |
||||
secp256k1_fe x; /* actual X: x/z^2 */ |
||||
secp256k1_fe y; /* actual Y: y/z^3 */ |
||||
secp256k1_fe z; |
||||
int infinity; /* whether this represents the point at infinity */ |
||||
} secp256k1_gej; |
||||
|
||||
#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} |
||||
#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} |
||||
|
||||
typedef struct { |
||||
secp256k1_fe_storage x; |
||||
secp256k1_fe_storage y; |
||||
} secp256k1_ge_storage; |
||||
|
||||
#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} |
||||
|
||||
#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) |
||||
|
||||
/** Set a group element equal to the point at infinity */ |
||||
static void secp256k1_ge_set_infinity(secp256k1_ge *r); |
||||
|
||||
/** Set a group element equal to the point with given X and Y coordinates */ |
||||
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); |
||||
|
||||
/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness
|
||||
* for Y. Return value indicates whether the result is valid. */ |
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); |
||||
|
||||
/** Check whether a group element is the point at infinity. */ |
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge *a); |
||||
|
||||
/** Check whether a group element is valid (i.e., on the curve). */ |
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); |
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); |
||||
|
||||
/** Set a group element equal to another which is given in jacobian coordinates */ |
||||
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); |
||||
|
||||
/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ |
||||
static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb); |
||||
|
||||
/** Set a batch of group elements equal to the inputs given in jacobian
|
||||
* coordinates (with known z-ratios). zr must contain the known z-ratios such |
||||
* that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ |
||||
static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr); |
||||
|
||||
/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to
|
||||
* the same global z "denominator". zr must contain the known z-ratios such |
||||
* that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y |
||||
* coordinates of the result are stored in r, the common z coordinate is |
||||
* stored in globalz. */ |
||||
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); |
||||
|
||||
/** Set a group element (jacobian) equal to the point at infinity. */ |
||||
static void secp256k1_gej_set_infinity(secp256k1_gej *r); |
||||
|
||||
/** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ |
||||
static void secp256k1_gej_set_xy(secp256k1_gej *r, const secp256k1_fe *x, const secp256k1_fe *y); |
||||
|
||||
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ |
||||
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); |
||||
|
||||
/** Compare the X coordinate of a group element (jacobian). */ |
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); |
||||
|
||||
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ |
||||
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); |
||||
|
||||
/** Check whether a group element is the point at infinity. */ |
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej *a); |
||||
|
||||
/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0).
|
||||
* a may not be zero. Constant time. */ |
||||
static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); |
||||
|
||||
/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ |
||||
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); |
||||
|
||||
/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ |
||||
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); |
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ |
||||
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); |
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient
|
||||
than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time |
||||
guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ |
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); |
||||
|
||||
/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ |
||||
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ |
||||
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); |
||||
#endif |
||||
|
||||
/** Clear a secp256k1_gej to prevent leaking sensitive information. */ |
||||
static void secp256k1_gej_clear(secp256k1_gej *r); |
||||
|
||||
/** Clear a secp256k1_ge to prevent leaking sensitive information. */ |
||||
static void secp256k1_ge_clear(secp256k1_ge *r); |
||||
|
||||
/** Convert a group element to the storage type. */ |
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); |
||||
|
||||
/** Convert a group element back from the storage type. */ |
||||
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); |
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ |
||||
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); |
||||
|
||||
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ |
||||
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); |
||||
|
||||
#endif |
@ -0,0 +1,632 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_GROUP_IMPL_H_ |
||||
#define _SECP256K1_GROUP_IMPL_H_ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "num.h" |
||||
#include "field.h" |
||||
#include "group.h" |
||||
|
||||
/** Generator for secp256k1, value 'g' defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1. |
||||
*/ |
||||
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( |
||||
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, |
||||
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, |
||||
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, |
||||
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL |
||||
); |
||||
|
||||
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { |
||||
secp256k1_fe zi2;
|
||||
secp256k1_fe zi3; |
||||
secp256k1_fe_sqr(&zi2, zi); |
||||
secp256k1_fe_mul(&zi3, &zi2, zi); |
||||
secp256k1_fe_mul(&r->x, &a->x, &zi2); |
||||
secp256k1_fe_mul(&r->y, &a->y, &zi3); |
||||
r->infinity = a->infinity; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_infinity(secp256k1_ge *r) { |
||||
r->infinity = 1; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { |
||||
r->infinity = 0; |
||||
r->x = *x; |
||||
r->y = *y; |
||||
} |
||||
|
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { |
||||
return a->infinity; |
||||
} |
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { |
||||
*r = *a; |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
|
||||
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { |
||||
secp256k1_fe z2, z3; |
||||
r->infinity = a->infinity; |
||||
secp256k1_fe_inv(&a->z, &a->z); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_mul(&z3, &a->z, &z2); |
||||
secp256k1_fe_mul(&a->x, &a->x, &z2); |
||||
secp256k1_fe_mul(&a->y, &a->y, &z3); |
||||
secp256k1_fe_set_int(&a->z, 1); |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { |
||||
secp256k1_fe z2, z3; |
||||
r->infinity = a->infinity; |
||||
if (a->infinity) { |
||||
return; |
||||
} |
||||
secp256k1_fe_inv_var(&a->z, &a->z); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_mul(&z3, &a->z, &z2); |
||||
secp256k1_fe_mul(&a->x, &a->x, &z2); |
||||
secp256k1_fe_mul(&a->y, &a->y, &z3); |
||||
secp256k1_fe_set_int(&a->z, 1); |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb) { |
||||
secp256k1_fe *az; |
||||
secp256k1_fe *azi; |
||||
size_t i; |
||||
size_t count = 0; |
||||
az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); |
||||
for (i = 0; i < len; i++) { |
||||
if (!a[i].infinity) { |
||||
az[count++] = a[i].z; |
||||
} |
||||
} |
||||
|
||||
azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); |
||||
secp256k1_fe_inv_all_var(count, azi, az); |
||||
free(az); |
||||
|
||||
count = 0; |
||||
for (i = 0; i < len; i++) { |
||||
r[i].infinity = a[i].infinity; |
||||
if (!a[i].infinity) { |
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); |
||||
} |
||||
} |
||||
free(azi); |
||||
} |
||||
|
||||
static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr) { |
||||
size_t i = len - 1; |
||||
secp256k1_fe zi; |
||||
|
||||
if (len > 0) { |
||||
/* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ |
||||
secp256k1_fe_inv(&zi, &a[i].z); |
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); |
||||
|
||||
/* Work out way backwards, using the z-ratios to scale the x/y values. */ |
||||
while (i > 0) { |
||||
secp256k1_fe_mul(&zi, &zi, &zr[i]); |
||||
i--; |
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { |
||||
size_t i = len - 1; |
||||
secp256k1_fe zs; |
||||
|
||||
if (len > 0) { |
||||
/* The z of the final point gives us the "global Z" for the table. */ |
||||
r[i].x = a[i].x; |
||||
r[i].y = a[i].y; |
||||
*globalz = a[i].z; |
||||
r[i].infinity = 0; |
||||
zs = zr[i]; |
||||
|
||||
/* Work our way backwards, using the z-ratios to scale the x/y values. */ |
||||
while (i > 0) { |
||||
if (i != len - 1) { |
||||
secp256k1_fe_mul(&zs, &zs, &zr[i]); |
||||
} |
||||
i--; |
||||
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void secp256k1_gej_set_infinity(secp256k1_gej *r) { |
||||
r->infinity = 1; |
||||
secp256k1_fe_set_int(&r->x, 0); |
||||
secp256k1_fe_set_int(&r->y, 0); |
||||
secp256k1_fe_set_int(&r->z, 0); |
||||
} |
||||
|
||||
static void secp256k1_gej_set_xy(secp256k1_gej *r, const secp256k1_fe *x, const secp256k1_fe *y) { |
||||
r->infinity = 0; |
||||
r->x = *x; |
||||
r->y = *y; |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
} |
||||
|
||||
static void secp256k1_gej_clear(secp256k1_gej *r) { |
||||
r->infinity = 0; |
||||
secp256k1_fe_clear(&r->x); |
||||
secp256k1_fe_clear(&r->y); |
||||
secp256k1_fe_clear(&r->z); |
||||
} |
||||
|
||||
static void secp256k1_ge_clear(secp256k1_ge *r) { |
||||
r->infinity = 0; |
||||
secp256k1_fe_clear(&r->x); |
||||
secp256k1_fe_clear(&r->y); |
||||
} |
||||
|
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { |
||||
secp256k1_fe x2, x3, c; |
||||
r->x = *x; |
||||
secp256k1_fe_sqr(&x2, x); |
||||
secp256k1_fe_mul(&x3, x, &x2); |
||||
r->infinity = 0; |
||||
secp256k1_fe_set_int(&c, 7); |
||||
secp256k1_fe_add(&c, &x3); |
||||
if (!secp256k1_fe_sqrt_var(&r->y, &c)) { |
||||
return 0; |
||||
} |
||||
secp256k1_fe_normalize_var(&r->y); |
||||
if (secp256k1_fe_is_odd(&r->y) != odd) { |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { |
||||
r->infinity = a->infinity; |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
} |
||||
|
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { |
||||
secp256k1_fe r, r2; |
||||
VERIFY_CHECK(!a->infinity); |
||||
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); |
||||
r2 = a->x; secp256k1_fe_normalize_weak(&r2); |
||||
return secp256k1_fe_equal_var(&r, &r2); |
||||
} |
||||
|
||||
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { |
||||
r->infinity = a->infinity; |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
r->z = a->z; |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
|
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { |
||||
return a->infinity; |
||||
} |
||||
|
||||
static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { |
||||
secp256k1_fe y2, x3, z2, z6; |
||||
if (a->infinity) { |
||||
return 0; |
||||
} |
||||
/** y^2 = x^3 + 7
|
||||
* (Y/Z^3)^2 = (X/Z^2)^3 + 7 |
||||
* Y^2 / Z^6 = X^3 / Z^6 + 7 |
||||
* Y^2 = X^3 + 7*Z^6 |
||||
*/ |
||||
secp256k1_fe_sqr(&y2, &a->y); |
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); |
||||
secp256k1_fe_mul_int(&z6, 7); |
||||
secp256k1_fe_add(&x3, &z6); |
||||
secp256k1_fe_normalize_weak(&x3); |
||||
return secp256k1_fe_equal_var(&y2, &x3); |
||||
} |
||||
|
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { |
||||
secp256k1_fe y2, x3, c; |
||||
if (a->infinity) { |
||||
return 0; |
||||
} |
||||
/* y^2 = x^3 + 7 */ |
||||
secp256k1_fe_sqr(&y2, &a->y); |
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
secp256k1_fe_set_int(&c, 7); |
||||
secp256k1_fe_add(&x3, &c); |
||||
secp256k1_fe_normalize_weak(&x3); |
||||
return secp256k1_fe_equal_var(&y2, &x3); |
||||
} |
||||
|
||||
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { |
||||
/* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe t1,t2,t3,t4; |
||||
/** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
|
||||
* Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have |
||||
* y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. |
||||
*/ |
||||
r->infinity = a->infinity; |
||||
if (r->infinity) { |
||||
if (rzr != NULL) { |
||||
secp256k1_fe_set_int(rzr, 1); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if (rzr != NULL) { |
||||
*rzr = a->y; |
||||
secp256k1_fe_normalize_weak(rzr); |
||||
secp256k1_fe_mul_int(rzr, 2); |
||||
} |
||||
|
||||
secp256k1_fe_mul(&r->z, &a->z, &a->y); |
||||
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ |
||||
secp256k1_fe_sqr(&t1, &a->x); |
||||
secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ |
||||
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ |
||||
secp256k1_fe_sqr(&t3, &a->y); |
||||
secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ |
||||
secp256k1_fe_sqr(&t4, &t3); |
||||
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ |
||||
secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ |
||||
r->x = t3; |
||||
secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ |
||||
secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ |
||||
secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ |
||||
secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ |
||||
secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ |
||||
secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ |
||||
secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ |
||||
secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ |
||||
secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ |
||||
} |
||||
|
||||
static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { |
||||
VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); |
||||
secp256k1_gej_double_var(r, a, rzr); |
||||
} |
||||
|
||||
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { |
||||
/* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; |
||||
|
||||
if (a->infinity) { |
||||
VERIFY_CHECK(rzr == NULL); |
||||
*r = *b; |
||||
return; |
||||
} |
||||
|
||||
if (b->infinity) { |
||||
if (rzr != NULL) { |
||||
secp256k1_fe_set_int(rzr, 1); |
||||
} |
||||
*r = *a; |
||||
return; |
||||
} |
||||
|
||||
r->infinity = 0; |
||||
secp256k1_fe_sqr(&z22, &b->z); |
||||
secp256k1_fe_sqr(&z12, &a->z); |
||||
secp256k1_fe_mul(&u1, &a->x, &z22); |
||||
secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); |
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) { |
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) { |
||||
secp256k1_gej_double_var(r, a, rzr); |
||||
} else { |
||||
if (rzr != NULL) { |
||||
secp256k1_fe_set_int(rzr, 0); |
||||
} |
||||
r->infinity = 1; |
||||
} |
||||
return; |
||||
} |
||||
secp256k1_fe_sqr(&i2, &i); |
||||
secp256k1_fe_sqr(&h2, &h); |
||||
secp256k1_fe_mul(&h3, &h, &h2); |
||||
secp256k1_fe_mul(&h, &h, &b->z); |
||||
if (rzr != NULL) { |
||||
*rzr = h; |
||||
} |
||||
secp256k1_fe_mul(&r->z, &a->z, &h); |
||||
secp256k1_fe_mul(&t, &u1, &h2); |
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); |
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); |
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); |
||||
secp256k1_fe_add(&r->y, &h3); |
||||
} |
||||
|
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { |
||||
/* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; |
||||
if (a->infinity) { |
||||
VERIFY_CHECK(rzr == NULL); |
||||
secp256k1_gej_set_ge(r, b); |
||||
return; |
||||
} |
||||
if (b->infinity) { |
||||
if (rzr != NULL) { |
||||
secp256k1_fe_set_int(rzr, 1); |
||||
} |
||||
*r = *a; |
||||
return; |
||||
} |
||||
r->infinity = 0; |
||||
|
||||
secp256k1_fe_sqr(&z12, &a->z); |
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); |
||||
secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); |
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) { |
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) { |
||||
secp256k1_gej_double_var(r, a, rzr); |
||||
} else { |
||||
if (rzr != NULL) { |
||||
secp256k1_fe_set_int(rzr, 0); |
||||
} |
||||
r->infinity = 1; |
||||
} |
||||
return; |
||||
} |
||||
secp256k1_fe_sqr(&i2, &i); |
||||
secp256k1_fe_sqr(&h2, &h); |
||||
secp256k1_fe_mul(&h3, &h, &h2); |
||||
if (rzr != NULL) { |
||||
*rzr = h; |
||||
} |
||||
secp256k1_fe_mul(&r->z, &a->z, &h); |
||||
secp256k1_fe_mul(&t, &u1, &h2); |
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); |
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); |
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); |
||||
secp256k1_fe_add(&r->y, &h3); |
||||
} |
||||
|
||||
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { |
||||
/* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; |
||||
|
||||
if (b->infinity) { |
||||
*r = *a; |
||||
return; |
||||
} |
||||
if (a->infinity) { |
||||
secp256k1_fe bzinv2, bzinv3; |
||||
r->infinity = b->infinity; |
||||
secp256k1_fe_sqr(&bzinv2, bzinv); |
||||
secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); |
||||
secp256k1_fe_mul(&r->x, &b->x, &bzinv2); |
||||
secp256k1_fe_mul(&r->y, &b->y, &bzinv3); |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
return; |
||||
} |
||||
r->infinity = 0; |
||||
|
||||
/** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to
|
||||
* secp256k1's isomorphism we can multiply the Z coordinates on both sides |
||||
* by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). |
||||
* This means that (rx,ry,rz) can be calculated as |
||||
* (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. |
||||
* The variable az below holds the modified Z coordinate for a, which is used |
||||
* for the computation of rx and ry, but not for rz. |
||||
*/ |
||||
secp256k1_fe_mul(&az, &a->z, bzinv); |
||||
|
||||
secp256k1_fe_sqr(&z12, &az); |
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); |
||||
secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); |
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); |
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) { |
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) { |
||||
secp256k1_gej_double_var(r, a, NULL); |
||||
} else { |
||||
r->infinity = 1; |
||||
} |
||||
return; |
||||
} |
||||
secp256k1_fe_sqr(&i2, &i); |
||||
secp256k1_fe_sqr(&h2, &h); |
||||
secp256k1_fe_mul(&h3, &h, &h2); |
||||
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); |
||||
secp256k1_fe_mul(&t, &u1, &h2); |
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); |
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); |
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); |
||||
secp256k1_fe_add(&r->y, &h3); |
||||
} |
||||
|
||||
|
||||
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { |
||||
/* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ |
||||
static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); |
||||
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; |
||||
secp256k1_fe m_alt, rr_alt; |
||||
int infinity, degenerate; |
||||
VERIFY_CHECK(!b->infinity); |
||||
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); |
||||
|
||||
/** In:
|
||||
* Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. |
||||
* In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. |
||||
* we find as solution for a unified addition/doubling formula: |
||||
* lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. |
||||
* x3 = lambda^2 - (x1 + x2) |
||||
* 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). |
||||
* |
||||
* Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: |
||||
* U1 = X1*Z2^2, U2 = X2*Z1^2 |
||||
* S1 = Y1*Z2^3, S2 = Y2*Z1^3 |
||||
* Z = Z1*Z2 |
||||
* T = U1+U2 |
||||
* M = S1+S2 |
||||
* Q = T*M^2 |
||||
* R = T^2-U1*U2 |
||||
* X3 = 4*(R^2-Q) |
||||
* Y3 = 4*(R*(3*Q-2*R^2)-M^4) |
||||
* Z3 = 2*M*Z |
||||
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) |
||||
* |
||||
* This formula has the benefit of being the same for both addition |
||||
* of distinct points and doubling. However, it breaks down in the |
||||
* case that either point is infinity, or that y1 = -y2. We handle |
||||
* these cases in the following ways: |
||||
* |
||||
* - If b is infinity we simply bail by means of a VERIFY_CHECK. |
||||
* |
||||
* - If a is infinity, we detect this, and at the end of the |
||||
* computation replace the result (which will be meaningless, |
||||
* but we compute to be constant-time) with b.x : b.y : 1. |
||||
* |
||||
* - If a = -b, we have y1 = -y2, which is a degenerate case. |
||||
* But here the answer is infinity, so we simply set the |
||||
* infinity flag of the result, overriding the computed values |
||||
* without even needing to cmov. |
||||
* |
||||
* - If y1 = -y2 but x1 != x2, which does occur thanks to certain |
||||
* properties of our curve (specifically, 1 has nontrivial cube |
||||
* roots in our field, and the curve equation has no x coefficient) |
||||
* then the answer is not infinity but also not given by the above |
||||
* equation. In this case, we cmov in place an alternate expression |
||||
* for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these |
||||
* expressions for lambda are defined, they are equal, and can be |
||||
* obtained from each other by multiplication by (y1 + y2)/(y1 + y2) |
||||
* then substitution of x^3 + 7 for y^2 (using the curve equation). |
||||
* For all pairs of nonzero points (a, b) at least one is defined, |
||||
* so this covers everything. |
||||
*/ |
||||
|
||||
secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ |
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ |
||||
secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ |
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ |
||||
secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ |
||||
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ |
||||
t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ |
||||
m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ |
||||
secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ |
||||
secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ |
||||
secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ |
||||
secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ |
||||
/** If lambda = R/M = 0/0 we have a problem (except in the "trivial"
|
||||
* case that Z = z1z2 = 0, and this is special-cased later on). */ |
||||
degenerate = secp256k1_fe_normalizes_to_zero(&m) & |
||||
secp256k1_fe_normalizes_to_zero(&rr); |
||||
/* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2.
|
||||
* This means either x1 == beta*x2 or beta*x1 == x2, where beta is |
||||
* a nontrivial cube root of one. In either case, an alternate |
||||
* non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), |
||||
* so we set R/M equal to this. */ |
||||
rr_alt = s1; |
||||
secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ |
||||
secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ |
||||
|
||||
secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); |
||||
secp256k1_fe_cmov(&m_alt, &m, !degenerate); |
||||
/* Now Ralt / Malt = lambda and is guaranteed not to be 0/0.
|
||||
* From here on out Ralt and Malt represent the numerator |
||||
* and denominator of lambda; R and M represent the explicit |
||||
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ |
||||
secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ |
||||
secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ |
||||
/* These two lines use the observation that either M == Malt or M == 0,
|
||||
* so M^3 * Malt is either Malt^4 (which is computed by squaring), or |
||||
* zero (which is "computed" by cmov). So the cost is one squaring |
||||
* versus two multiplications. */ |
||||
secp256k1_fe_sqr(&n, &n); |
||||
secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ |
||||
secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ |
||||
secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ |
||||
infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); |
||||
secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ |
||||
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ |
||||
secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ |
||||
secp256k1_fe_normalize_weak(&t); |
||||
r->x = t; /* r->x = Ralt^2-Q (1) */ |
||||
secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ |
||||
secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ |
||||
secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ |
||||
secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ |
||||
secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ |
||||
secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ |
||||
|
||||
/** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ |
||||
secp256k1_fe_cmov(&r->x, &b->x, a->infinity); |
||||
secp256k1_fe_cmov(&r->y, &b->y, a->infinity); |
||||
secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); |
||||
r->infinity = infinity; |
||||
} |
||||
|
||||
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { |
||||
/* Operations: 4 mul, 1 sqr */ |
||||
secp256k1_fe zz; |
||||
VERIFY_CHECK(!secp256k1_fe_is_zero(s)); |
||||
secp256k1_fe_sqr(&zz, s); |
||||
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ |
||||
secp256k1_fe_mul(&r->y, &r->y, &zz); |
||||
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ |
||||
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ |
||||
} |
||||
|
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { |
||||
secp256k1_fe x, y; |
||||
VERIFY_CHECK(!a->infinity); |
||||
x = a->x; |
||||
secp256k1_fe_normalize(&x); |
||||
y = a->y; |
||||
secp256k1_fe_normalize(&y); |
||||
secp256k1_fe_to_storage(&r->x, &x); |
||||
secp256k1_fe_to_storage(&r->y, &y); |
||||
} |
||||
|
||||
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { |
||||
secp256k1_fe_from_storage(&r->x, &a->x); |
||||
secp256k1_fe_from_storage(&r->y, &a->y); |
||||
r->infinity = 0; |
||||
} |
||||
|
||||
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { |
||||
secp256k1_fe_storage_cmov(&r->x, &a->x, flag); |
||||
secp256k1_fe_storage_cmov(&r->y, &a->y, flag); |
||||
} |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { |
||||
static const secp256k1_fe beta = SECP256K1_FE_CONST( |
||||
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, |
||||
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul |
||||
); |
||||
*r = *a; |
||||
secp256k1_fe_mul(&r->x, &r->x, &beta); |
||||
} |
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,9 @@ |
||||
include_HEADERS += include/secp256k1_ecdh.h
|
||||
noinst_HEADERS += src/modules/ecdh/main_impl.h
|
||||
noinst_HEADERS += src/modules/ecdh/tests_impl.h
|
||||
if USE_BENCHMARK |
||||
noinst_PROGRAMS += bench_ecdh
|
||||
bench_ecdh_SOURCES = src/bench_ecdh.c
|
||||
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS)
|
||||
bench_ecdh_LDFLAGS = -static
|
||||
endif |
@ -0,0 +1,54 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_MODULE_ECDH_MAIN_ |
||||
#define _SECP256K1_MODULE_ECDH_MAIN_ |
||||
|
||||
#include "include/secp256k1_ecdh.h" |
||||
#include "ecmult_const_impl.h" |
||||
|
||||
int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
secp256k1_gej res; |
||||
secp256k1_ge pt; |
||||
secp256k1_scalar s; |
||||
ARG_CHECK(result != NULL); |
||||
ARG_CHECK(point != NULL); |
||||
ARG_CHECK(scalar != NULL); |
||||
(void)ctx; |
||||
|
||||
secp256k1_pubkey_load(ctx, &pt, point); |
||||
secp256k1_scalar_set_b32(&s, scalar, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&s)) { |
||||
ret = 0; |
||||
} else { |
||||
unsigned char x[32]; |
||||
unsigned char y[1]; |
||||
secp256k1_sha256_t sha; |
||||
|
||||
secp256k1_ecmult_const(&res, &pt, &s); |
||||
secp256k1_ge_set_gej(&pt, &res); |
||||
/* Compute a hash of the point in compressed form
|
||||
* Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not |
||||
* expect its output to be secret and has a timing sidechannel. */ |
||||
secp256k1_fe_normalize(&pt.x); |
||||
secp256k1_fe_normalize(&pt.y); |
||||
secp256k1_fe_get_b32(x, &pt.x); |
||||
y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); |
||||
|
||||
secp256k1_sha256_initialize(&sha); |
||||
secp256k1_sha256_write(&sha, y, sizeof(y)); |
||||
secp256k1_sha256_write(&sha, x, sizeof(x)); |
||||
secp256k1_sha256_finalize(&sha, result); |
||||
ret = 1; |
||||
} |
||||
|
||||
secp256k1_scalar_clear(&s); |
||||
return ret; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,75 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2015 Andrew Poelstra * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_MODULE_ECDH_TESTS_ |
||||
#define _SECP256K1_MODULE_ECDH_TESTS_ |
||||
|
||||
void test_ecdh_generator_basepoint(void) { |
||||
unsigned char s_one[32] = { 0 }; |
||||
secp256k1_pubkey point[2]; |
||||
int i; |
||||
|
||||
s_one[31] = 1; |
||||
/* Check against pubkey creation when the basepoint is the generator */ |
||||
for (i = 0; i < 100; ++i) { |
||||
secp256k1_sha256_t sha; |
||||
unsigned char s_b32[32]; |
||||
unsigned char output_ecdh[32]; |
||||
unsigned char output_ser[32]; |
||||
unsigned char point_ser[33]; |
||||
size_t point_ser_len = sizeof(point_ser); |
||||
secp256k1_scalar s; |
||||
|
||||
random_scalar_order(&s); |
||||
secp256k1_scalar_get_b32(s_b32, &s); |
||||
|
||||
/* compute using ECDH function */ |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); |
||||
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); |
||||
/* compute "explicitly" */ |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); |
||||
CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); |
||||
CHECK(point_ser_len == sizeof(point_ser)); |
||||
secp256k1_sha256_initialize(&sha); |
||||
secp256k1_sha256_write(&sha, point_ser, point_ser_len); |
||||
secp256k1_sha256_finalize(&sha, output_ser); |
||||
/* compare */ |
||||
CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); |
||||
} |
||||
} |
||||
|
||||
void test_bad_scalar(void) { |
||||
unsigned char s_zero[32] = { 0 }; |
||||
unsigned char s_overflow[32] = { |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, |
||||
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, |
||||
0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 |
||||
}; |
||||
unsigned char s_rand[32] = { 0 }; |
||||
unsigned char output[32]; |
||||
secp256k1_scalar rand; |
||||
secp256k1_pubkey point; |
||||
|
||||
/* Create random point */ |
||||
random_scalar_order(&rand); |
||||
secp256k1_scalar_get_b32(s_rand, &rand); |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); |
||||
|
||||
/* Try to multiply it by bad values */ |
||||
CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); |
||||
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); |
||||
/* ...and a good one */ |
||||
s_overflow[31] -= 1; |
||||
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); |
||||
} |
||||
|
||||
void run_ecdh_tests(void) { |
||||
test_ecdh_generator_basepoint(); |
||||
test_bad_scalar(); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,9 @@ |
||||
include_HEADERS += include/secp256k1_recovery.h
|
||||
noinst_HEADERS += src/modules/recovery/main_impl.h
|
||||
noinst_HEADERS += src/modules/recovery/tests_impl.h
|
||||
if USE_BENCHMARK |
||||
noinst_PROGRAMS += bench_recover
|
||||
bench_recover_SOURCES = src/bench_recover.c
|
||||
bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS)
|
||||
bench_recover_LDFLAGS = -static
|
||||
endif |
@ -0,0 +1,156 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ |
||||
#define _SECP256K1_MODULE_RECOVERY_MAIN_ |
||||
|
||||
#include "include/secp256k1_recovery.h" |
||||
|
||||
static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { |
||||
(void)ctx; |
||||
if (sizeof(secp256k1_scalar) == 32) { |
||||
/* When the secp256k1_scalar type is exactly 32 byte, use its
|
||||
* representation inside secp256k1_ecdsa_signature, as conversion is very fast. |
||||
* Note that secp256k1_ecdsa_signature_save must use the same representation. */ |
||||
memcpy(r, &sig->data[0], 32); |
||||
memcpy(s, &sig->data[32], 32); |
||||
} else { |
||||
secp256k1_scalar_set_b32(r, &sig->data[0], NULL); |
||||
secp256k1_scalar_set_b32(s, &sig->data[32], NULL); |
||||
} |
||||
*recid = sig->data[64]; |
||||
} |
||||
|
||||
static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { |
||||
if (sizeof(secp256k1_scalar) == 32) { |
||||
memcpy(&sig->data[0], r, 32); |
||||
memcpy(&sig->data[32], s, 32); |
||||
} else { |
||||
secp256k1_scalar_get_b32(&sig->data[0], r); |
||||
secp256k1_scalar_get_b32(&sig->data[32], s); |
||||
} |
||||
sig->data[64] = recid; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { |
||||
secp256k1_scalar r, s; |
||||
int ret = 1; |
||||
int overflow = 0; |
||||
|
||||
(void)ctx; |
||||
ARG_CHECK(sig != NULL); |
||||
ARG_CHECK(input64 != NULL); |
||||
ARG_CHECK(recid >= 0 && recid <= 3); |
||||
|
||||
secp256k1_scalar_set_b32(&r, &input64[0], &overflow); |
||||
ret &= !overflow; |
||||
secp256k1_scalar_set_b32(&s, &input64[32], &overflow); |
||||
ret &= !overflow; |
||||
if (ret) { |
||||
secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); |
||||
} else { |
||||
memset(sig, 0, sizeof(*sig)); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { |
||||
secp256k1_scalar r, s; |
||||
|
||||
(void)ctx; |
||||
ARG_CHECK(output64 != NULL); |
||||
ARG_CHECK(sig != NULL); |
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); |
||||
secp256k1_scalar_get_b32(&output64[0], &r); |
||||
secp256k1_scalar_get_b32(&output64[32], &s); |
||||
return 1; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { |
||||
secp256k1_scalar r, s; |
||||
int recid; |
||||
|
||||
(void)ctx; |
||||
ARG_CHECK(sig != NULL); |
||||
ARG_CHECK(sigin != NULL); |
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); |
||||
secp256k1_ecdsa_signature_save(sig, &r, &s); |
||||
return 1; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { |
||||
secp256k1_scalar r, s; |
||||
secp256k1_scalar sec, non, msg; |
||||
int recid; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(signature != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
/* Fail if the secret key is invalid. */ |
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) { |
||||
unsigned int count = 0; |
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL); |
||||
while (1) { |
||||
unsigned char nonce32[32]; |
||||
ret = noncefp(nonce32, seckey, msg32, NULL, (void*)noncedata, count); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
||||
memset(nonce32, 0, 32); |
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) { |
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { |
||||
break; |
||||
} |
||||
} |
||||
count++; |
||||
} |
||||
secp256k1_scalar_clear(&msg); |
||||
secp256k1_scalar_clear(&non); |
||||
secp256k1_scalar_clear(&sec); |
||||
} |
||||
if (ret) { |
||||
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); |
||||
} else { |
||||
memset(signature, 0, sizeof(*signature)); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { |
||||
secp256k1_ge q; |
||||
secp256k1_scalar r, s; |
||||
secp256k1_scalar m; |
||||
int recid; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(signature != NULL); |
||||
ARG_CHECK(pubkey != NULL); |
||||
|
||||
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); |
||||
ARG_CHECK(recid >= 0 && recid < 4); |
||||
secp256k1_scalar_set_b32(&m, msg32, NULL); |
||||
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { |
||||
secp256k1_pubkey_save(pubkey, &q); |
||||
return 1; |
||||
} else { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,249 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ |
||||
#define _SECP256K1_MODULE_RECOVERY_TESTS_ |
||||
|
||||
void test_ecdsa_recovery_end_to_end(void) { |
||||
unsigned char extra[32] = {0x00}; |
||||
unsigned char privkey[32]; |
||||
unsigned char message[32]; |
||||
secp256k1_ecdsa_signature signature[5]; |
||||
secp256k1_ecdsa_recoverable_signature rsignature[5]; |
||||
unsigned char sig[74]; |
||||
secp256k1_pubkey pubkey; |
||||
secp256k1_pubkey recpubkey; |
||||
int recid = 0; |
||||
|
||||
/* Generate a random key and message. */ |
||||
{ |
||||
secp256k1_scalar msg, key; |
||||
random_scalar_order_test(&msg); |
||||
random_scalar_order_test(&key); |
||||
secp256k1_scalar_get_b32(privkey, &key); |
||||
secp256k1_scalar_get_b32(message, &msg); |
||||
} |
||||
|
||||
/* Construct and verify corresponding public key. */ |
||||
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); |
||||
|
||||
/* Serialize/parse compact and verify/recover. */ |
||||
extra[0] = 0; |
||||
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); |
||||
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); |
||||
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); |
||||
extra[31] = 1; |
||||
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); |
||||
extra[31] = 0; |
||||
extra[0] = 1; |
||||
CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); |
||||
memset(&rsignature[4], 0, sizeof(rsignature[4])); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); |
||||
/* Parse compact (with recovery id) and recover. */ |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); |
||||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); |
||||
/* Serialize/destroy/parse signature and verify again. */ |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); |
||||
sig[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); |
||||
/* Recover again */ |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || |
||||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); |
||||
} |
||||
|
||||
/* Tests several edge cases. */ |
||||
void test_ecdsa_recovery_edge_cases(void) { |
||||
const unsigned char msg32[32] = { |
||||
'T', 'h', 'i', 's', ' ', 'i', 's', ' ', |
||||
'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', |
||||
'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', |
||||
's', 's', 'a', 'g', 'e', '.', '.', '.' |
||||
}; |
||||
const unsigned char sig64[64] = { |
||||
/* Generated by signing the above message with nonce 'This is the nonce we will use...'
|
||||
* and secret key 0 (which is not valid), resulting in recid 0. */ |
||||
0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, |
||||
0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, |
||||
0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, |
||||
0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, |
||||
0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, |
||||
0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, |
||||
0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, |
||||
0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 |
||||
}; |
||||
secp256k1_pubkey pubkey; |
||||
/* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ |
||||
const unsigned char sigb64[64] = { |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
||||
}; |
||||
secp256k1_pubkey pubkeyb; |
||||
secp256k1_ecdsa_recoverable_signature rsig; |
||||
secp256k1_ecdsa_signature sig; |
||||
int recid; |
||||
|
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); |
||||
CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); |
||||
CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); |
||||
CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); |
||||
|
||||
for (recid = 0; recid < 4; recid++) { |
||||
int i; |
||||
int recid2; |
||||
/* (4,4) encoded in DER. */ |
||||
unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; |
||||
unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; |
||||
unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; |
||||
unsigned char sigbderalt1[39] = { |
||||
0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, |
||||
}; |
||||
unsigned char sigbderalt2[39] = { |
||||
0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
||||
}; |
||||
unsigned char sigbderalt3[40] = { |
||||
0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, |
||||
}; |
||||
unsigned char sigbderalt4[40] = { |
||||
0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
||||
}; |
||||
/* (order + r,4) encoded in DER. */ |
||||
unsigned char sigbderlong[40] = { |
||||
0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, |
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, |
||||
0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, |
||||
0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 |
||||
}; |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); |
||||
for (recid2 = 0; recid2 < 4; recid2++) { |
||||
secp256k1_pubkey pubkey2b; |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); |
||||
/* Verifying with (order + r,4) should always fail. */ |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 0); |
||||
} |
||||
/* DER parsing tests. */ |
||||
/* Zero length r/s. */ |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); |
||||
/* Leading zeros. */ |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); |
||||
sigbderalt3[4] = 1; |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); |
||||
sigbderalt4[7] = 1; |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); |
||||
/* Damage signature. */ |
||||
sigbder[7]++; |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); |
||||
sigbder[7]--; |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); |
||||
for(i = 0; i < 8; i++) { |
||||
int c; |
||||
unsigned char orig = sigbder[i]; |
||||
/*Try every single-byte change.*/ |
||||
for (c = 0; c < 256; c++) { |
||||
if (c == orig ) { |
||||
continue; |
||||
} |
||||
sigbder[i] = c; |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); |
||||
} |
||||
sigbder[i] = orig; |
||||
} |
||||
} |
||||
|
||||
/* Test r/s equal to zero */ |
||||
{ |
||||
/* (1,1) encoded in DER. */ |
||||
unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; |
||||
unsigned char sigc64[64] = { |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
||||
}; |
||||
secp256k1_pubkey pubkeyc; |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); |
||||
sigcder[4] = 0; |
||||
sigc64[31] = 0; |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); |
||||
sigcder[4] = 1; |
||||
sigcder[7] = 0; |
||||
sigc64[31] = 1; |
||||
sigc64[63] = 0; |
||||
CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); |
||||
CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); |
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); |
||||
CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); |
||||
} |
||||
} |
||||
|
||||
void run_recovery_tests(void) { |
||||
int i; |
||||
for (i = 0; i < 64*count; i++) { |
||||
test_ecdsa_recovery_end_to_end(); |
||||
} |
||||
test_ecdsa_recovery_edge_cases(); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,11 @@ |
||||
include_HEADERS += include/secp256k1_schnorr.h
|
||||
noinst_HEADERS += src/modules/schnorr/main_impl.h
|
||||
noinst_HEADERS += src/modules/schnorr/schnorr.h
|
||||
noinst_HEADERS += src/modules/schnorr/schnorr_impl.h
|
||||
noinst_HEADERS += src/modules/schnorr/tests_impl.h
|
||||
if USE_BENCHMARK |
||||
noinst_PROGRAMS += bench_schnorr_verify
|
||||
bench_schnorr_verify_SOURCES = src/bench_schnorr_verify.c
|
||||
bench_schnorr_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
|
||||
bench_schnorr_verify_LDFLAGS = -static
|
||||
endif |
@ -0,0 +1,164 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef SECP256K1_MODULE_SCHNORR_MAIN |
||||
#define SECP256K1_MODULE_SCHNORR_MAIN |
||||
|
||||
#include "include/secp256k1_schnorr.h" |
||||
#include "modules/schnorr/schnorr_impl.h" |
||||
|
||||
static void secp256k1_schnorr_msghash_sha256(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) { |
||||
secp256k1_sha256_t sha; |
||||
secp256k1_sha256_initialize(&sha); |
||||
secp256k1_sha256_write(&sha, r32, 32); |
||||
secp256k1_sha256_write(&sha, msg32, 32); |
||||
secp256k1_sha256_finalize(&sha, h32); |
||||
} |
||||
|
||||
static const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 "; |
||||
|
||||
int secp256k1_schnorr_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { |
||||
secp256k1_scalar sec, non; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
unsigned int count = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sig64 != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); |
||||
while (1) { |
||||
unsigned char nonce32[32]; |
||||
ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)noncedata, count); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
||||
memset(nonce32, 0, 32); |
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) { |
||||
if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, NULL, secp256k1_schnorr_msghash_sha256, msg32)) { |
||||
break; |
||||
} |
||||
} |
||||
count++; |
||||
} |
||||
if (!ret) { |
||||
memset(sig64, 0, 64); |
||||
} |
||||
secp256k1_scalar_clear(&non); |
||||
secp256k1_scalar_clear(&sec); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_schnorr_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { |
||||
secp256k1_ge q; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sig64 != NULL); |
||||
ARG_CHECK(pubkey != NULL); |
||||
|
||||
secp256k1_pubkey_load(ctx, &q, pubkey); |
||||
return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32); |
||||
} |
||||
|
||||
int secp256k1_schnorr_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *sig64, const unsigned char *msg32) { |
||||
secp256k1_ge q; |
||||
|
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sig64 != NULL); |
||||
ARG_CHECK(pubkey != NULL); |
||||
|
||||
if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32)) { |
||||
secp256k1_pubkey_save(pubkey, &q); |
||||
return 1; |
||||
} else { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
int secp256k1_schnorr_generate_nonce_pair(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, unsigned char *privnonce32, const unsigned char *sec32, const unsigned char *msg32, secp256k1_nonce_function noncefp, const void* noncedata) { |
||||
int count = 0; |
||||
int ret = 1; |
||||
secp256k1_gej Qj; |
||||
secp256k1_ge Q; |
||||
secp256k1_scalar sec; |
||||
|
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sec32 != NULL); |
||||
ARG_CHECK(pubnonce != NULL); |
||||
ARG_CHECK(privnonce32 != NULL); |
||||
|
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
do { |
||||
int overflow; |
||||
ret = noncefp(privnonce32, sec32, msg32, secp256k1_schnorr_algo16, (void*)noncedata, count++); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&sec, privnonce32, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&sec)) { |
||||
continue; |
||||
} |
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sec); |
||||
secp256k1_ge_set_gej(&Q, &Qj); |
||||
|
||||
secp256k1_pubkey_save(pubnonce, &Q); |
||||
break; |
||||
} while(1); |
||||
|
||||
secp256k1_scalar_clear(&sec); |
||||
if (!ret) { |
||||
memset(pubnonce, 0, sizeof(*pubnonce)); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_schnorr_partial_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *sec32, const secp256k1_pubkey *pubnonce_others, const unsigned char *secnonce32) { |
||||
int overflow = 0; |
||||
secp256k1_scalar sec, non; |
||||
secp256k1_ge pubnon; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sig64 != NULL); |
||||
ARG_CHECK(sec32 != NULL); |
||||
ARG_CHECK(secnonce32 != NULL); |
||||
ARG_CHECK(pubnonce_others != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&sec, sec32, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&sec)) { |
||||
return -1; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, secnonce32, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&non)) { |
||||
return -1; |
||||
} |
||||
secp256k1_pubkey_load(ctx, &pubnon, pubnonce_others); |
||||
return secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, &pubnon, secp256k1_schnorr_msghash_sha256, msg32); |
||||
} |
||||
|
||||
int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, int n) { |
||||
ARG_CHECK(sig64 != NULL); |
||||
ARG_CHECK(n >= 1); |
||||
ARG_CHECK(sig64sin != NULL); |
||||
return secp256k1_schnorr_sig_combine(sig64, n, sig64sin); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,20 @@ |
||||
/***********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php. *
|
||||
***********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_MODULE_SCHNORR_H_ |
||||
#define _SECP256K1_MODULE_SCHNORR_H_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
|
||||
typedef void (*secp256k1_schnorr_msghash)(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32); |
||||
|
||||
static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32); |
||||
static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32); |
||||
static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32); |
||||
static int secp256k1_schnorr_sig_combine(unsigned char *sig64, int n, const unsigned char * const *sig64ins); |
||||
|
||||
#endif |
@ -0,0 +1,207 @@ |
||||
/***********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php. *
|
||||
***********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_SCHNORR_IMPL_H_ |
||||
#define _SECP256K1_SCHNORR_IMPL_H_ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "schnorr.h" |
||||
#include "num.h" |
||||
#include "field.h" |
||||
#include "group.h" |
||||
#include "ecmult.h" |
||||
#include "ecmult_gen.h" |
||||
|
||||
/**
|
||||
* Custom Schnorr-based signature scheme. They support multiparty signing, public key |
||||
* recovery and batch validation. |
||||
* |
||||
* Rationale for verifying R's y coordinate: |
||||
* In order to support batch validation and public key recovery, the full R point must |
||||
* be known to verifiers, rather than just its x coordinate. In order to not risk |
||||
* being more strict in batch validation than normal validation, validators must be |
||||
* required to reject signatures with incorrect y coordinate. This is only possible |
||||
* by including a (relatively slow) field inverse, or a field square root. However, |
||||
* batch validation offers potentially much higher benefits than this cost. |
||||
* |
||||
* Rationale for having an implicit y coordinate oddness: |
||||
* If we commit to having the full R point known to verifiers, there are two mechanism. |
||||
* Either include its oddness in the signature, or give it an implicit fixed value. |
||||
* As the R y coordinate can be flipped by a simple negation of the nonce, we choose the |
||||
* latter, as it comes with nearly zero impact on signing or validation performance, and |
||||
* saves a byte in the signature. |
||||
* |
||||
* Signing: |
||||
* Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0) |
||||
* |
||||
* Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate nonce). |
||||
* Compute 32-byte r, the serialization of R's x coordinate. |
||||
* Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order. |
||||
* Compute scalar s = k - h * x. |
||||
* The signature is (r, s). |
||||
* |
||||
* |
||||
* Verification: |
||||
* Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s) |
||||
* |
||||
* Signature is invalid if s >= order. |
||||
* Signature is invalid if r >= p. |
||||
* Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order. |
||||
* Option 1 (faster for single verification): |
||||
* Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y coordinate is odd. |
||||
* Signature is valid if the serialization of R's x coordinate equals r. |
||||
* Option 2 (allows batch validation and pubkey recovery): |
||||
* Decompress x coordinate r into point R, with odd y coordinate. Fail if R is not on the curve. |
||||
* Signature is valid if R + h * Q + s * G == 0. |
||||
*/ |
||||
|
||||
static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { |
||||
secp256k1_gej Rj; |
||||
secp256k1_ge Ra; |
||||
unsigned char h32[32]; |
||||
secp256k1_scalar h, s; |
||||
int overflow; |
||||
secp256k1_scalar n; |
||||
|
||||
if (secp256k1_scalar_is_zero(key) || secp256k1_scalar_is_zero(nonce)) { |
||||
return 0; |
||||
} |
||||
n = *nonce; |
||||
|
||||
secp256k1_ecmult_gen(ctx, &Rj, &n); |
||||
if (pubnonce != NULL) { |
||||
secp256k1_gej_add_ge(&Rj, &Rj, pubnonce); |
||||
} |
||||
secp256k1_ge_set_gej(&Ra, &Rj); |
||||
secp256k1_fe_normalize(&Ra.y); |
||||
if (secp256k1_fe_is_odd(&Ra.y)) { |
||||
/* R's y coordinate is odd, which is not allowed (see rationale above).
|
||||
Force it to be even by negating the nonce. Note that this even works |
||||
for multiparty signing, as the R point is known to all participants, |
||||
which can all decide to flip the sign in unison, resulting in the |
||||
overall R point to be negated too. */ |
||||
secp256k1_scalar_negate(&n, &n); |
||||
} |
||||
secp256k1_fe_normalize(&Ra.x); |
||||
secp256k1_fe_get_b32(sig64, &Ra.x); |
||||
hash(h32, sig64, msg32); |
||||
overflow = 0; |
||||
secp256k1_scalar_set_b32(&h, h32, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&h)) { |
||||
secp256k1_scalar_clear(&n); |
||||
return 0; |
||||
} |
||||
secp256k1_scalar_mul(&s, &h, key); |
||||
secp256k1_scalar_negate(&s, &s); |
||||
secp256k1_scalar_add(&s, &s, &n); |
||||
secp256k1_scalar_clear(&n); |
||||
secp256k1_scalar_get_b32(sig64 + 32, &s); |
||||
return 1; |
||||
} |
||||
|
||||
static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { |
||||
secp256k1_gej Qj, Rj; |
||||
secp256k1_ge Ra; |
||||
secp256k1_fe Rx; |
||||
secp256k1_scalar h, s; |
||||
unsigned char hh[32]; |
||||
int overflow; |
||||
|
||||
if (secp256k1_ge_is_infinity(pubkey)) { |
||||
return 0; |
||||
} |
||||
hash(hh, sig64, msg32); |
||||
overflow = 0; |
||||
secp256k1_scalar_set_b32(&h, hh, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&h)) { |
||||
return 0; |
||||
} |
||||
overflow = 0; |
||||
secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); |
||||
if (overflow) { |
||||
return 0; |
||||
} |
||||
if (!secp256k1_fe_set_b32(&Rx, sig64)) { |
||||
return 0; |
||||
} |
||||
secp256k1_gej_set_ge(&Qj, pubkey); |
||||
secp256k1_ecmult(ctx, &Rj, &Qj, &h, &s); |
||||
if (secp256k1_gej_is_infinity(&Rj)) { |
||||
return 0; |
||||
} |
||||
secp256k1_ge_set_gej_var(&Ra, &Rj); |
||||
secp256k1_fe_normalize_var(&Ra.y); |
||||
if (secp256k1_fe_is_odd(&Ra.y)) { |
||||
return 0; |
||||
} |
||||
return secp256k1_fe_equal_var(&Rx, &Ra.x); |
||||
} |
||||
|
||||
static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { |
||||
secp256k1_gej Qj, Rj; |
||||
secp256k1_ge Ra; |
||||
secp256k1_fe Rx; |
||||
secp256k1_scalar h, s; |
||||
unsigned char hh[32]; |
||||
int overflow; |
||||
|
||||
hash(hh, sig64, msg32); |
||||
overflow = 0; |
||||
secp256k1_scalar_set_b32(&h, hh, &overflow); |
||||
if (overflow || secp256k1_scalar_is_zero(&h)) { |
||||
return 0; |
||||
} |
||||
overflow = 0; |
||||
secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); |
||||
if (overflow) { |
||||
return 0; |
||||
} |
||||
if (!secp256k1_fe_set_b32(&Rx, sig64)) { |
||||
return 0; |
||||
} |
||||
if (!secp256k1_ge_set_xo_var(&Ra, &Rx, 0)) { |
||||
return 0; |
||||
} |
||||
secp256k1_gej_set_ge(&Rj, &Ra); |
||||
secp256k1_scalar_inverse_var(&h, &h); |
||||
secp256k1_scalar_negate(&s, &s); |
||||
secp256k1_scalar_mul(&s, &s, &h); |
||||
secp256k1_ecmult(ctx, &Qj, &Rj, &h, &s); |
||||
if (secp256k1_gej_is_infinity(&Qj)) { |
||||
return 0; |
||||
} |
||||
secp256k1_ge_set_gej(pubkey, &Qj); |
||||
return 1; |
||||
} |
||||
|
||||
static int secp256k1_schnorr_sig_combine(unsigned char *sig64, int n, const unsigned char * const *sig64ins) { |
||||
secp256k1_scalar s = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); |
||||
int i; |
||||
for (i = 0; i < n; i++) { |
||||
secp256k1_scalar si; |
||||
int overflow; |
||||
secp256k1_scalar_set_b32(&si, sig64ins[i] + 32, &overflow); |
||||
if (overflow) { |
||||
return -1; |
||||
} |
||||
if (i) { |
||||
if (memcmp(sig64ins[i - 1], sig64ins[i], 32) != 0) { |
||||
return -1; |
||||
} |
||||
} |
||||
secp256k1_scalar_add(&s, &s, &si); |
||||
} |
||||
if (secp256k1_scalar_is_zero(&s)) { |
||||
return 0; |
||||
} |
||||
memcpy(sig64, sig64ins[0], 32); |
||||
secp256k1_scalar_get_b32(sig64 + 32, &s); |
||||
secp256k1_scalar_clear(&s); |
||||
return 1; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,175 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2014-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef SECP256K1_MODULE_SCHNORR_TESTS |
||||
#define SECP256K1_MODULE_SCHNORR_TESTS |
||||
|
||||
#include "include/secp256k1_schnorr.h" |
||||
|
||||
void test_schnorr_end_to_end(void) { |
||||
unsigned char privkey[32]; |
||||
unsigned char message[32]; |
||||
unsigned char schnorr_signature[64]; |
||||
secp256k1_pubkey pubkey, recpubkey; |
||||
|
||||
/* Generate a random key and message. */ |
||||
{ |
||||
secp256k1_scalar key; |
||||
random_scalar_order_test(&key); |
||||
secp256k1_scalar_get_b32(privkey, &key); |
||||
secp256k1_rand256_test(message); |
||||
} |
||||
|
||||
/* Construct and verify corresponding public key. */ |
||||
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); |
||||
|
||||
/* Schnorr sign. */ |
||||
CHECK(secp256k1_schnorr_sign(ctx, schnorr_signature, message, privkey, NULL, NULL) == 1); |
||||
CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 1); |
||||
CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) == 1); |
||||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); |
||||
/* Destroy signature and verify again. */ |
||||
schnorr_signature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); |
||||
CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0); |
||||
CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) != 1 || |
||||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); |
||||
} |
||||
|
||||
/** Horribly broken hash function. Do not use for anything but tests. */ |
||||
void test_schnorr_hash(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) { |
||||
int i; |
||||
for (i = 0; i < 32; i++) { |
||||
h32[i] = r32[i] ^ msg32[i]; |
||||
} |
||||
} |
||||
|
||||
void test_schnorr_sign_verify(void) { |
||||
unsigned char msg32[32]; |
||||
unsigned char sig64[3][64]; |
||||
secp256k1_gej pubkeyj[3]; |
||||
secp256k1_ge pubkey[3]; |
||||
secp256k1_scalar nonce[3], key[3]; |
||||
int i = 0; |
||||
int k; |
||||
|
||||
secp256k1_rand256_test(msg32); |
||||
|
||||
for (k = 0; k < 3; k++) { |
||||
random_scalar_order_test(&key[k]); |
||||
|
||||
do { |
||||
random_scalar_order_test(&nonce[k]); |
||||
if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64[k], &key[k], &nonce[k], NULL, &test_schnorr_hash, msg32)) { |
||||
break; |
||||
} |
||||
} while(1); |
||||
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj[k], &key[k]); |
||||
secp256k1_ge_set_gej_var(&pubkey[k], &pubkeyj[k]); |
||||
CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32)); |
||||
|
||||
for (i = 0; i < 4; i++) { |
||||
int pos = secp256k1_rand32() % 64; |
||||
int mod = 1 + (secp256k1_rand32() % 255); |
||||
sig64[k][pos] ^= mod; |
||||
CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32) == 0); |
||||
sig64[k][pos] ^= mod; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void test_schnorr_threshold(void) { |
||||
unsigned char msg[32]; |
||||
unsigned char sec[5][32]; |
||||
secp256k1_pubkey pub[5]; |
||||
unsigned char nonce[5][32]; |
||||
secp256k1_pubkey pubnonce[5]; |
||||
unsigned char sig[5][64]; |
||||
const unsigned char* sigs[5]; |
||||
unsigned char allsig[64]; |
||||
const secp256k1_pubkey* pubs[5]; |
||||
secp256k1_pubkey allpub; |
||||
int n, i; |
||||
int damage; |
||||
int ret = 0; |
||||
|
||||
damage = (secp256k1_rand32() % 2) ? (1 + (secp256k1_rand32() % 4)) : 0; |
||||
secp256k1_rand256_test(msg); |
||||
n = 2 + (secp256k1_rand32() % 4); |
||||
for (i = 0; i < n; i++) { |
||||
do { |
||||
secp256k1_rand256_test(sec[i]); |
||||
} while (!secp256k1_ec_seckey_verify(ctx, sec[i])); |
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pub[i], sec[i])); |
||||
CHECK(secp256k1_schnorr_generate_nonce_pair(ctx, &pubnonce[i], nonce[i], msg, sec[i], NULL, NULL)); |
||||
pubs[i] = &pub[i]; |
||||
} |
||||
if (damage == 1) { |
||||
nonce[secp256k1_rand32() % n][secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255); |
||||
} else if (damage == 2) { |
||||
sec[secp256k1_rand32() % n][secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255); |
||||
} |
||||
for (i = 0; i < n; i++) { |
||||
secp256k1_pubkey allpubnonce; |
||||
const secp256k1_pubkey *pubnonces[4]; |
||||
int j; |
||||
for (j = 0; j < i; j++) { |
||||
pubnonces[j] = &pubnonce[j]; |
||||
} |
||||
for (j = i + 1; j < n; j++) { |
||||
pubnonces[j - 1] = &pubnonce[j]; |
||||
} |
||||
CHECK(secp256k1_ec_pubkey_combine(ctx, &allpubnonce, pubnonces, n - 1)); |
||||
ret |= (secp256k1_schnorr_partial_sign(ctx, sig[i], msg, sec[i], &allpubnonce, nonce[i]) != 1) * 1; |
||||
sigs[i] = sig[i]; |
||||
} |
||||
if (damage == 3) { |
||||
sig[secp256k1_rand32() % n][secp256k1_rand32() % 64] ^= 1 + (secp256k1_rand32() % 255); |
||||
} |
||||
ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2; |
||||
if ((ret & 1) == 0) { |
||||
ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4; |
||||
} |
||||
if (damage == 4) { |
||||
allsig[secp256k1_rand32() % 32] ^= 1 + (secp256k1_rand32() % 255); |
||||
} |
||||
if ((ret & 7) == 0) { |
||||
ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8; |
||||
} |
||||
CHECK((ret == 0) == (damage == 0)); |
||||
} |
||||
|
||||
void test_schnorr_recovery(void) { |
||||
unsigned char msg32[32]; |
||||
unsigned char sig64[64]; |
||||
secp256k1_ge Q; |
||||
|
||||
secp256k1_rand256_test(msg32); |
||||
secp256k1_rand256_test(sig64); |
||||
secp256k1_rand256_test(sig64 + 32); |
||||
if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1) { |
||||
CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1); |
||||
} |
||||
} |
||||
|
||||
void run_schnorr_tests(void) { |
||||
int i; |
||||
for (i = 0; i < 32*count; i++) { |
||||
test_schnorr_end_to_end(); |
||||
} |
||||
for (i = 0; i < 32 * count; i++) { |
||||
test_schnorr_sign_verify(); |
||||
} |
||||
for (i = 0; i < 16 * count; i++) { |
||||
test_schnorr_recovery(); |
||||
} |
||||
for (i = 0; i < 10 * count; i++) { |
||||
test_schnorr_threshold(); |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,104 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_SCALAR_ |
||||
#define _SECP256K1_SCALAR_ |
||||
|
||||
#include "num.h" |
||||
|
||||
#if defined HAVE_CONFIG_H |
||||
#include "libsecp256k1-config.h" |
||||
#endif |
||||
|
||||
#if defined(USE_SCALAR_4X64) |
||||
#include "scalar_4x64.h" |
||||
#elif defined(USE_SCALAR_8X32) |
||||
#include "scalar_8x32.h" |
||||
#else |
||||
#error "Please select scalar implementation" |
||||
#endif |
||||
|
||||
/** Clear a scalar to prevent the leak of sensitive data. */ |
||||
static void secp256k1_scalar_clear(secp256k1_scalar *r); |
||||
|
||||
/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ |
||||
static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); |
||||
|
||||
/** Access bits from a scalar. Not constant time. */ |
||||
static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); |
||||
|
||||
/** Set a scalar from a big endian byte array. */ |
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); |
||||
|
||||
/** Set a scalar to an unsigned integer. */ |
||||
static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); |
||||
|
||||
/** Convert a scalar to a byte array. */ |
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); |
||||
|
||||
/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ |
||||
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); |
||||
|
||||
/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ |
||||
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); |
||||
|
||||
/** Multiply two scalars (modulo the group order). */ |
||||
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); |
||||
|
||||
/** Shift a scalar right by some amount strictly between 0 and 16, returning
|
||||
* the low bits that were shifted off */ |
||||
static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); |
||||
|
||||
/** Compute the square of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); |
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); |
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ |
||||
static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); |
||||
|
||||
/** Compute the complement of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); |
||||
|
||||
/** Check whether a scalar equals zero. */ |
||||
static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); |
||||
|
||||
/** Check whether a scalar equals one. */ |
||||
static int secp256k1_scalar_is_one(const secp256k1_scalar *a); |
||||
|
||||
/** Check whether a scalar, considered as an nonnegative integer, is even. */ |
||||
static int secp256k1_scalar_is_even(const secp256k1_scalar *a); |
||||
|
||||
/** Check whether a scalar is higher than the group order divided by 2. */ |
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar *a); |
||||
|
||||
/** Conditionally negate a number, in constant time.
|
||||
* Returns -1 if the number was negated, 1 otherwise */ |
||||
static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); |
||||
|
||||
#ifndef USE_NUM_NONE |
||||
/** Convert a scalar to a number. */ |
||||
static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); |
||||
|
||||
/** Get the order of the group as a number. */ |
||||
static void secp256k1_scalar_order_get_num(secp256k1_num *r); |
||||
#endif |
||||
|
||||
/** Compare two scalars. */ |
||||
static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Find r1 and r2 such that r1+r2*2^128 = a. */ |
||||
static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); |
||||
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ |
||||
static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); |
||||
#endif |
||||
|
||||
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ |
||||
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); |
||||
|
||||
#endif |
@ -0,0 +1,513 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013-2015 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#define SECP256K1_BUILD (1) |
||||
|
||||
#include "include/secp256k1.h" |
||||
|
||||
#include "util.h" |
||||
#include "num_impl.h" |
||||
#include "field_impl.h" |
||||
#include "scalar_impl.h" |
||||
#include "group_impl.h" |
||||
#include "ecmult_impl.h" |
||||
#include "ecmult_const_impl.h" |
||||
#include "ecmult_gen_impl.h" |
||||
#include "ecdsa_impl.h" |
||||
#include "eckey_impl.h" |
||||
#include "hash_impl.h" |
||||
|
||||
#define ARG_CHECK(cond) do { \ |
||||
if (EXPECT(!(cond), 0)) { \
|
||||
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0) |
||||
|
||||
static void default_illegal_callback_fn(const char* str, void* data) { |
||||
(void)data; |
||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); |
||||
abort(); |
||||
} |
||||
|
||||
static const secp256k1_callback default_illegal_callback = { |
||||
default_illegal_callback_fn, |
||||
NULL |
||||
}; |
||||
|
||||
static void default_error_callback_fn(const char* str, void* data) { |
||||
(void)data; |
||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); |
||||
abort(); |
||||
} |
||||
|
||||
static const secp256k1_callback default_error_callback = { |
||||
default_error_callback_fn, |
||||
NULL |
||||
}; |
||||
|
||||
|
||||
struct secp256k1_context_struct { |
||||
secp256k1_ecmult_context ecmult_ctx; |
||||
secp256k1_ecmult_gen_context ecmult_gen_ctx; |
||||
secp256k1_callback illegal_callback; |
||||
secp256k1_callback error_callback; |
||||
}; |
||||
|
||||
secp256k1_context* secp256k1_context_create(unsigned int flags) { |
||||
secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); |
||||
ret->illegal_callback = default_illegal_callback; |
||||
ret->error_callback = default_error_callback; |
||||
|
||||
secp256k1_ecmult_context_init(&ret->ecmult_ctx); |
||||
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); |
||||
|
||||
if (flags & SECP256K1_CONTEXT_SIGN) { |
||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); |
||||
} |
||||
if (flags & SECP256K1_CONTEXT_VERIFY) { |
||||
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { |
||||
secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); |
||||
ret->illegal_callback = ctx->illegal_callback; |
||||
ret->error_callback = ctx->error_callback; |
||||
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); |
||||
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); |
||||
return ret; |
||||
} |
||||
|
||||
void secp256k1_context_destroy(secp256k1_context* ctx) { |
||||
if (ctx != NULL) { |
||||
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); |
||||
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); |
||||
|
||||
free(ctx); |
||||
} |
||||
} |
||||
|
||||
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { |
||||
if (fun == NULL) { |
||||
fun = default_illegal_callback_fn; |
||||
} |
||||
ctx->illegal_callback.fn = fun; |
||||
ctx->illegal_callback.data = data; |
||||
} |
||||
|
||||
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { |
||||
if (fun == NULL) { |
||||
fun = default_error_callback_fn; |
||||
} |
||||
ctx->error_callback.fn = fun; |
||||
ctx->error_callback.data = data; |
||||
} |
||||
|
||||
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { |
||||
if (sizeof(secp256k1_ge_storage) == 64) { |
||||
/* When the secp256k1_ge_storage type is exactly 64 byte, use its
|
||||
* representation inside secp256k1_pubkey, as conversion is very fast. |
||||
* Note that secp256k1_pubkey_save must use the same representation. */ |
||||
secp256k1_ge_storage s; |
||||
memcpy(&s, &pubkey->data[0], 64); |
||||
secp256k1_ge_from_storage(ge, &s); |
||||
} else { |
||||
/* Otherwise, fall back to 32-byte big endian for X and Y. */ |
||||
secp256k1_fe x, y; |
||||
secp256k1_fe_set_b32(&x, pubkey->data); |
||||
secp256k1_fe_set_b32(&y, pubkey->data + 32); |
||||
secp256k1_ge_set_xy(ge, &x, &y); |
||||
} |
||||
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); |
||||
return 1; |
||||
} |
||||
|
||||
static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { |
||||
if (sizeof(secp256k1_ge_storage) == 64) { |
||||
secp256k1_ge_storage s; |
||||
secp256k1_ge_to_storage(&s, ge); |
||||
memcpy(&pubkey->data[0], &s, 64); |
||||
} else { |
||||
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); |
||||
secp256k1_fe_normalize_var(&ge->x); |
||||
secp256k1_fe_normalize_var(&ge->y); |
||||
secp256k1_fe_get_b32(pubkey->data, &ge->x); |
||||
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); |
||||
} |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { |
||||
secp256k1_ge Q; |
||||
|
||||
(void)ctx; |
||||
if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
return 0; |
||||
} |
||||
secp256k1_pubkey_save(pubkey, &Q); |
||||
secp256k1_ge_clear(&Q); |
||||
return 1; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { |
||||
secp256k1_ge Q; |
||||
|
||||
(void)ctx; |
||||
return (secp256k1_pubkey_load(ctx, &Q, pubkey) && |
||||
secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags)); |
||||
} |
||||
|
||||
static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { |
||||
(void)ctx; |
||||
if (sizeof(secp256k1_scalar) == 32) { |
||||
/* When the secp256k1_scalar type is exactly 32 byte, use its
|
||||
* representation inside secp256k1_ecdsa_signature, as conversion is very fast. |
||||
* Note that secp256k1_ecdsa_signature_save must use the same representation. */ |
||||
memcpy(r, &sig->data[0], 32); |
||||
memcpy(s, &sig->data[32], 32); |
||||
} else { |
||||
secp256k1_scalar_set_b32(r, &sig->data[0], NULL); |
||||
secp256k1_scalar_set_b32(s, &sig->data[32], NULL); |
||||
} |
||||
} |
||||
|
||||
static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { |
||||
if (sizeof(secp256k1_scalar) == 32) { |
||||
memcpy(&sig->data[0], r, 32); |
||||
memcpy(&sig->data[32], s, 32); |
||||
} else { |
||||
secp256k1_scalar_get_b32(&sig->data[0], r); |
||||
secp256k1_scalar_get_b32(&sig->data[32], s); |
||||
} |
||||
} |
||||
|
||||
int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { |
||||
secp256k1_scalar r, s; |
||||
|
||||
(void)ctx; |
||||
ARG_CHECK(sig != NULL); |
||||
ARG_CHECK(input != NULL); |
||||
|
||||
if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { |
||||
secp256k1_ecdsa_signature_save(sig, &r, &s); |
||||
return 1; |
||||
} else { |
||||
memset(sig, 0, sizeof(*sig)); |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { |
||||
secp256k1_scalar r, s; |
||||
|
||||
(void)ctx; |
||||
ARG_CHECK(output != NULL); |
||||
ARG_CHECK(outputlen != NULL); |
||||
ARG_CHECK(sig != NULL); |
||||
|
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
||||
return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); |
||||
} |
||||
|
||||
int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { |
||||
secp256k1_ge q; |
||||
secp256k1_scalar r, s; |
||||
secp256k1_scalar m; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(sig != NULL); |
||||
ARG_CHECK(pubkey != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL); |
||||
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); |
||||
return (secp256k1_pubkey_load(ctx, &q, pubkey) && |
||||
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); |
||||
} |
||||
|
||||
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { |
||||
unsigned char keydata[112]; |
||||
int keylen = 64; |
||||
secp256k1_rfc6979_hmac_sha256_t rng; |
||||
unsigned int i; |
||||
/* We feed a byte array to the PRNG as input, consisting of:
|
||||
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. |
||||
* - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. |
||||
* - optionally 16 extra bytes with the algorithm name (the extra data bytes |
||||
* are set to zeroes when not present, while the algorithm name is). |
||||
*/ |
||||
memcpy(keydata, key32, 32); |
||||
memcpy(keydata + 32, msg32, 32); |
||||
if (data != NULL) { |
||||
memcpy(keydata + 64, data, 32); |
||||
keylen = 96; |
||||
} |
||||
if (algo16 != NULL) { |
||||
memset(keydata + keylen, 0, 96 - keylen); |
||||
memcpy(keydata + 96, algo16, 16); |
||||
keylen = 112; |
||||
} |
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); |
||||
memset(keydata, 0, sizeof(keydata)); |
||||
for (i = 0; i <= counter; i++) { |
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
||||
} |
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng); |
||||
return 1; |
||||
} |
||||
|
||||
const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; |
||||
const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; |
||||
|
||||
int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { |
||||
secp256k1_scalar r, s; |
||||
secp256k1_scalar sec, non, msg; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(msg32 != NULL); |
||||
ARG_CHECK(signature != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
/* Fail if the secret key is invalid. */ |
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) { |
||||
unsigned int count = 0; |
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL); |
||||
while (1) { |
||||
unsigned char nonce32[32]; |
||||
ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
||||
memset(nonce32, 0, 32); |
||||
if (!overflow && !secp256k1_scalar_is_zero(&non)) { |
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { |
||||
break; |
||||
} |
||||
} |
||||
count++; |
||||
} |
||||
secp256k1_scalar_clear(&msg); |
||||
secp256k1_scalar_clear(&non); |
||||
secp256k1_scalar_clear(&sec); |
||||
} |
||||
if (ret) { |
||||
secp256k1_ecdsa_signature_save(signature, &r, &s); |
||||
} else { |
||||
memset(signature, 0, sizeof(*signature)); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { |
||||
secp256k1_scalar sec; |
||||
int ret; |
||||
int overflow; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
(void)ctx; |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
ret = !overflow && !secp256k1_scalar_is_zero(&sec); |
||||
secp256k1_scalar_clear(&sec); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { |
||||
secp256k1_gej pj; |
||||
secp256k1_ge p; |
||||
secp256k1_scalar sec; |
||||
int overflow; |
||||
int ret = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
ARG_CHECK(pubkey != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); |
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); |
||||
secp256k1_ge_set_gej(&p, &pj); |
||||
secp256k1_pubkey_save(pubkey, &p); |
||||
secp256k1_scalar_clear(&sec); |
||||
if (!ret) { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { |
||||
secp256k1_scalar term; |
||||
secp256k1_scalar sec; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
ARG_CHECK(tweak != NULL); |
||||
(void)ctx; |
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); |
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); |
||||
|
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &sec); |
||||
} |
||||
|
||||
secp256k1_scalar_clear(&sec); |
||||
secp256k1_scalar_clear(&term); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { |
||||
secp256k1_ge p; |
||||
secp256k1_scalar term; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(pubkey != NULL); |
||||
ARG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); |
||||
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
||||
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term); |
||||
if (ret) { |
||||
secp256k1_pubkey_save(pubkey, &p); |
||||
} else { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { |
||||
secp256k1_scalar factor; |
||||
secp256k1_scalar sec; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
ARG_CHECK(tweak != NULL); |
||||
(void)ctx; |
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); |
||||
ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &sec); |
||||
} |
||||
|
||||
secp256k1_scalar_clear(&sec); |
||||
secp256k1_scalar_clear(&factor); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { |
||||
secp256k1_ge p; |
||||
secp256k1_scalar factor; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); |
||||
ARG_CHECK(pubkey != NULL); |
||||
ARG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
||||
if (!overflow && secp256k1_pubkey_load(ctx, &p, pubkey)) { |
||||
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor); |
||||
if (ret) { |
||||
secp256k1_pubkey_save(pubkey, &p); |
||||
} else { |
||||
memset(pubkey, 0, sizeof(*pubkey)); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_export(const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) { |
||||
secp256k1_scalar key; |
||||
int ret = 0; |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(seckey != NULL); |
||||
ARG_CHECK(privkey != NULL); |
||||
ARG_CHECK(privkeylen != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
|
||||
secp256k1_scalar_set_b32(&key, seckey, NULL); |
||||
ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, flags); |
||||
secp256k1_scalar_clear(&key); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_import(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen) { |
||||
secp256k1_scalar key; |
||||
int ret = 0; |
||||
ARG_CHECK(seckey != NULL); |
||||
ARG_CHECK(privkey != NULL); |
||||
(void)ctx; |
||||
|
||||
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &key); |
||||
} |
||||
secp256k1_scalar_clear(&key); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { |
||||
VERIFY_CHECK(ctx != NULL); |
||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); |
||||
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); |
||||
return 1; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, int n) { |
||||
int i; |
||||
secp256k1_gej Qj; |
||||
secp256k1_ge Q; |
||||
|
||||
ARG_CHECK(pubnonce != NULL); |
||||
ARG_CHECK(n >= 1); |
||||
ARG_CHECK(pubnonces != NULL); |
||||
|
||||
secp256k1_gej_set_infinity(&Qj); |
||||
|
||||
for (i = 0; i < n; i++) { |
||||
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); |
||||
secp256k1_gej_add_ge(&Qj, &Qj, &Q); |
||||
} |
||||
if (secp256k1_gej_is_infinity(&Qj)) { |
||||
memset(pubnonce, 0, sizeof(*pubnonce)); |
||||
return 0; |
||||
} |
||||
secp256k1_ge_set_gej(&Q, &Qj); |
||||
secp256k1_pubkey_save(pubnonce, &Q); |
||||
return 1; |
||||
} |
||||
|
||||
#ifdef ENABLE_MODULE_ECDH |
||||
# include "modules/ecdh/main_impl.h" |
||||
#endif |
||||
|
||||
#ifdef ENABLE_MODULE_SCHNORR |
||||
# include "modules/schnorr/main_impl.h" |
||||
#endif |
||||
|
||||
#ifdef ENABLE_MODULE_RECOVERY |
||||
# include "modules/recovery/main_impl.h" |
||||
#endif |
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@ |
||||
language: c |
||||
compiler: |
||||
- clang |
||||
- gcc |
||||
install: |
||||
- sudo apt-get install -qq libssl-dev |
||||
- if [ "$BIGNUM" = "gmp" -o "$BIGNUM" = "auto" ]; then sudo apt-get install --no-install-recommends --no-upgrade -qq libgmp-dev; fi |
||||
- if [ -n "$EXTRAPACKAGES" ]; then sudo apt-get update && sudo apt-get install --no-install-recommends --no-upgrade $EXTRAPACKAGES; fi |
||||
env: |
||||
global: |
||||
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no ASM=no BUILD=check EXTRAFLAGS= HOST= EXTRAPACKAGES= |
||||
matrix: |
||||
- SCALAR=32bit |
||||
- SCALAR=64bit |
||||
- FIELD=64bit |
||||
- FIELD=64bit ENDOMORPHISM=yes |
||||
- FIELD=64bit ASM=x86_64 |
||||
- FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 |
||||
- FIELD=32bit |
||||
- FIELD=32bit ENDOMORPHISM=yes |
||||
- BIGNUM=no |
||||
- BIGNUM=no ENDOMORPHISM=yes |
||||
- BUILD=distcheck |
||||
- EXTRAFLAGS=CFLAGS=-DDETERMINISTIC |
||||
- HOST=i686-linux-gnu EXTRAPACKAGES="gcc-multilib" |
||||
- HOST=i686-linux-gnu EXTRAPACKAGES="gcc-multilib" ENDOMORPHISM=yes |
||||
before_script: ./autogen.sh |
||||
script: |
||||
- if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi |
||||
- if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi |
||||
- ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR $EXTRAFLAGS $USE_HOST && make -j2 $BUILD |
||||
os: linux |
@ -1,61 +0,0 @@ |
||||
dnl libsecp25k1 helper checks |
||||
AC_DEFUN([SECP_INT128_CHECK],[ |
||||
has_int128=$ac_cv_type___int128 |
||||
]) |
||||
|
||||
dnl |
||||
AC_DEFUN([SECP_64BIT_ASM_CHECK],[ |
||||
AC_MSG_CHECKING(for x86_64 assembly availability) |
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ |
||||
#include <stdint.h>]],[[ |
||||
uint64_t a = 11, tmp; |
||||
__asm__ __volatile__("movq $0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); |
||||
]])],[has_64bit_asm=yes],[has_64bit_asm=no]) |
||||
AC_MSG_RESULT([$has_64bit_asm]) |
||||
]) |
||||
|
||||
dnl |
||||
AC_DEFUN([SECP_OPENSSL_CHECK],[ |
||||
if test x"$use_pkgconfig" = x"yes"; then |
||||
: #NOP |
||||
m4_ifdef([PKG_CHECK_MODULES],[ |
||||
PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) |
||||
if test x"$has_libcrypto" = x"yes"; then |
||||
TEMP_LIBS="$LIBS" |
||||
LIBS="$LIBS $CRYPTO_LIBS" |
||||
AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) |
||||
LIBS="$TEMP_LIBS" |
||||
fi |
||||
]) |
||||
else |
||||
AC_CHECK_HEADER(openssl/crypto.h,[AC_CHECK_LIB(crypto, main,[has_libcrypto=yes; CRYPTO_LIBS=-lcrypto; AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])] |
||||
)]) |
||||
LIBS= |
||||
fi |
||||
if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then |
||||
AC_MSG_CHECKING(for EC functions in libcrypto) |
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ |
||||
#include <openssl/ec.h> |
||||
#include <openssl/ecdsa.h> |
||||
#include <openssl/obj_mac.h>]],[[ |
||||
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); |
||||
ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); |
||||
ECDSA_verify(0, NULL, 0, NULL, 0, eckey); |
||||
EC_KEY_free(eckey); |
||||
]])],[has_openssl_ec=yes],[has_openssl_ec=no]) |
||||
AC_MSG_RESULT([$has_openssl_ec]) |
||||
fi |
||||
]) |
||||
|
||||
dnl |
||||
AC_DEFUN([SECP_GMP_CHECK],[ |
||||
if test x"$has_gmp" != x"yes"; then |
||||
CPPFLAGS_TEMP="$CPPFLAGS" |
||||
CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" |
||||
LIBS_TEMP="$LIBS" |
||||
LIBS="$GMP_LIBS $LIBS" |
||||
AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) |
||||
CPPFLAGS="$CPPFLAGS_TEMP" |
||||
LIBS="$LIBS_TEMP" |
||||
fi |
||||
]) |
@ -1,295 +0,0 @@ |
||||
#ifndef _SECP256K1_ |
||||
# define _SECP256K1_ |
||||
|
||||
# ifdef __cplusplus |
||||
extern "C" { |
||||
# endif |
||||
|
||||
# if !defined(SECP256K1_GNUC_PREREQ) |
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__) |
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) \ |
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) |
||||
# else |
||||
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 |
||||
# endif |
||||
# endif |
||||
|
||||
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) |
||||
# if SECP256K1_GNUC_PREREQ(2,7) |
||||
# define SECP256K1_INLINE __inline__ |
||||
# elif (defined(_MSC_VER)) |
||||
# define SECP256K1_INLINE __inline |
||||
# else |
||||
# define SECP256K1_INLINE |
||||
# endif |
||||
# else |
||||
# define SECP256K1_INLINE inline |
||||
# endif |
||||
|
||||
/**Warning attributes
|
||||
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out |
||||
* some paranoid null checks. */ |
||||
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) |
||||
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) |
||||
# else |
||||
# define SECP256K1_WARN_UNUSED_RESULT |
||||
# endif |
||||
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) |
||||
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) |
||||
# else |
||||
# define SECP256K1_ARG_NONNULL(_x) |
||||
# endif |
||||
|
||||
|
||||
/** Flags to pass to secp256k1_start. */ |
||||
# define SECP256K1_START_VERIFY (1 << 0) |
||||
# define SECP256K1_START_SIGN (1 << 1) |
||||
|
||||
/** Initialize the library. This may take some time (10-100 ms).
|
||||
* You need to call this before calling any other function. |
||||
* It cannot run in parallel with any other functions, but once |
||||
* secp256k1_start() returns, all other functions are thread-safe. |
||||
*/ |
||||
void secp256k1_start(unsigned int flags); |
||||
|
||||
/** Free all memory associated with this library. After this, no
|
||||
* functions can be called anymore, except secp256k1_start() |
||||
*/ |
||||
void secp256k1_stop(void); |
||||
|
||||
/** Verify an ECDSA signature.
|
||||
* Returns: 1: correct signature |
||||
* 0: incorrect signature |
||||
* -1: invalid public key |
||||
* -2: invalid signature |
||||
* In: msg32: the 32-byte message hash being verified (cannot be NULL) |
||||
* sig: the signature being verified (cannot be NULL) |
||||
* siglen: the length of the signature |
||||
* pubkey: the public key to verify with (cannot be NULL) |
||||
* pubkeylen: the length of pubkey |
||||
* Requires starting using SECP256K1_START_VERIFY. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( |
||||
const unsigned char *msg32, |
||||
const unsigned char *sig, |
||||
int siglen, |
||||
const unsigned char *pubkey, |
||||
int pubkeylen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. |
||||
* In: msg32: the 32-byte message hash being verified (will not be NULL) |
||||
* key32: pointer to a 32-byte secret key (will not be NULL) |
||||
* attempt: how many iterations we have tried to find a nonce. |
||||
* This will almost always be 0, but different attempt values |
||||
* are required to result in a different nonce. |
||||
* data: Arbitrary data pointer that is passed through. |
||||
* Out: nonce32: pointer to a 32-byte array to be filled by the function. |
||||
* Except for test cases, this function should compute some cryptographic hash of |
||||
* the message, the key and the attempt. |
||||
*/ |
||||
typedef int (*secp256k1_nonce_function_t)( |
||||
unsigned char *nonce32, |
||||
const unsigned char *msg32, |
||||
const unsigned char *key32, |
||||
unsigned int attempt, |
||||
const void *data |
||||
); |
||||
|
||||
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
|
||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of |
||||
* extra entropy. |
||||
*/ |
||||
extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979; |
||||
|
||||
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ |
||||
extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; |
||||
|
||||
|
||||
/** Create an ECDSA signature.
|
||||
* Returns: 1: signature created |
||||
* 0: the nonce generation function failed, the private key was invalid, or there is not |
||||
* enough space in the signature (as indicated by siglen). |
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL) |
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used |
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) |
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL) |
||||
* In/Out: siglen: pointer to an int with the length of sig, which will be updated |
||||
* to contain the actual signature length (<=72). If 0 is returned, this will be |
||||
* set to zero. |
||||
* Requires starting using SECP256K1_START_SIGN. |
||||
* |
||||
* The sig always has an s value in the lower half of the range (From 0x1 |
||||
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, |
||||
* inclusive), unlike many other implementations. |
||||
* With ECDSA a third-party can can forge a second distinct signature |
||||
* of the same message given a single initial signature without knowing |
||||
* the key by setting s to its additive inverse mod-order, 'flipping' the |
||||
* sign of the random point R which is not included in the signature. |
||||
* Since the forgery is of the same message this isn't universally |
||||
* problematic, but in systems where message malleability or uniqueness |
||||
* of signatures is important this can cause issues. This forgery can be |
||||
* blocked by all verifiers forcing signers to use a canonical form. The |
||||
* lower-S form reduces the size of signatures slightly on average when |
||||
* variable length encodings (such as DER) are used and is cheap to |
||||
* verify, making it a good choice. Security of always using lower-S is |
||||
* assured because anyone can trivially modify a signature after the |
||||
* fact to enforce this property. Adjusting it inside the signing |
||||
* function avoids the need to re-serialize or have curve specific |
||||
* constants outside of the library. By always using a canonical form |
||||
* even in applications where it isn't needed it becomes possible to |
||||
* impose a requirement later if a need is discovered. |
||||
* No other forms of ECDSA malleability are known and none seem likely, |
||||
* but there is no formal proof that ECDSA, even with this additional |
||||
* restriction, is free of other malleability. Commonly used serialization |
||||
* schemes will also accept various non-unique encodings, so care should |
||||
* be taken when this property is required for an application. |
||||
*/ |
||||
int secp256k1_ecdsa_sign( |
||||
const unsigned char *msg32, |
||||
unsigned char *sig, |
||||
int *siglen, |
||||
const unsigned char *seckey, |
||||
secp256k1_nonce_function_t noncefp, |
||||
const void *ndata |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Create a compact ECDSA signature (64 byte + recovery id).
|
||||
* Returns: 1: signature created |
||||
* 0: the nonce generation function failed, or the secret key was invalid. |
||||
* In: msg32: the 32-byte message hash being signed (cannot be NULL) |
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used |
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) |
||||
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL) |
||||
* In case 0 is returned, the returned signature length will be zero. |
||||
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL) |
||||
* Requires starting using SECP256K1_START_SIGN. |
||||
*/ |
||||
int secp256k1_ecdsa_sign_compact( |
||||
const unsigned char *msg32, |
||||
unsigned char *sig64, |
||||
const unsigned char *seckey, |
||||
secp256k1_nonce_function_t noncefp, |
||||
const void *ndata, |
||||
int *recid |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Recover an ECDSA public key from a compact signature.
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature). |
||||
* 0: otherwise. |
||||
* In: msg32: the 32-byte message hash assumed to be signed (cannot be NULL) |
||||
* sig64: signature as 64 byte array (cannot be NULL) |
||||
* compressed: whether to recover a compressed or uncompressed pubkey |
||||
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact) |
||||
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL) |
||||
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL) |
||||
* Requires starting using SECP256K1_START_VERIFY. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact( |
||||
const unsigned char *msg32, |
||||
const unsigned char *sig64, |
||||
unsigned char *pubkey, |
||||
int *pubkeylen, |
||||
int compressed, |
||||
int recid |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); |
||||
|
||||
/** Verify an ECDSA secret key.
|
||||
* Returns: 1: secret key is valid |
||||
* 0: secret key is invalid |
||||
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const unsigned char *seckey) SECP256K1_ARG_NONNULL(1); |
||||
|
||||
/** Just validate a public key.
|
||||
* Returns: 1: valid public key |
||||
* 0: invalid public key |
||||
* In: pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL). |
||||
* pubkeylen: length of pubkey |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) SECP256K1_ARG_NONNULL(1); |
||||
|
||||
/** Compute the public key for a secret key.
|
||||
* In: compressed: whether the computed public key should be compressed |
||||
* seckey: pointer to a 32-byte private key (cannot be NULL) |
||||
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) |
||||
* area to store the public key (cannot be NULL) |
||||
* pubkeylen: pointer to int that will be updated to contains the pubkey's |
||||
* length (cannot be NULL) |
||||
* Returns: 1: secret was valid, public key stores |
||||
* 0: secret was invalid, try again. |
||||
* Requires starting using SECP256K1_START_SIGN. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( |
||||
unsigned char *pubkey, |
||||
int *pubkeylen, |
||||
const unsigned char *seckey, |
||||
int compressed |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Decompress a public key.
|
||||
* In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key. |
||||
It must contain a 33-byte or 65-byte public key already (cannot be NULL) |
||||
* pubkeylen: pointer to the size of the public key pointed to by pubkey (cannot be NULL) |
||||
It will be updated to reflect the new size. |
||||
* Returns: 0 if the passed public key was invalid, 1 otherwise. If 1 is returned, the |
||||
pubkey is replaced with its decompressed version. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress( |
||||
unsigned char *pubkey, |
||||
int *pubkeylen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); |
||||
|
||||
/** Export a private key in DER format. */ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export( |
||||
const unsigned char *seckey, |
||||
unsigned char *privkey, |
||||
int *privkeylen, |
||||
int compressed |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Import a private key in DER format. */ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import( |
||||
unsigned char *seckey, |
||||
const unsigned char *privkey, |
||||
int privkeylen |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); |
||||
|
||||
/** Tweak a private key by adding tweak to it. */ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( |
||||
unsigned char *seckey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); |
||||
|
||||
/** Tweak a public key by adding tweak times the generator to it.
|
||||
* Requires starting with SECP256K1_START_VERIFY. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( |
||||
unsigned char *pubkey, |
||||
int pubkeylen, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
/** Tweak a private key by multiplying it with tweak. */ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( |
||||
unsigned char *seckey, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); |
||||
|
||||
/** Tweak a public key by multiplying it with tweak.
|
||||
* Requires starting with SECP256K1_START_VERIFY. |
||||
*/ |
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( |
||||
unsigned char *pubkey, |
||||
int pubkeylen, |
||||
const unsigned char *tweak |
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); |
||||
|
||||
# ifdef __cplusplus |
||||
} |
||||
# endif |
||||
|
||||
#endif |
@ -1,23 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECDSA_ |
||||
#define _SECP256K1_ECDSA_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
|
||||
typedef struct { |
||||
secp256k1_scalar_t r, s; |
||||
} secp256k1_ecdsa_sig_t; |
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); |
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); |
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message); |
||||
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid); |
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid); |
||||
|
||||
#endif |
@ -1,24 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECKEY_ |
||||
#define _SECP256K1_ECKEY_ |
||||
|
||||
#include "group.h" |
||||
#include "scalar.h" |
||||
|
||||
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); |
||||
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); |
||||
|
||||
static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen); |
||||
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed); |
||||
|
||||
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); |
||||
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak); |
||||
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); |
||||
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak); |
||||
|
||||
#endif |
@ -1,19 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_ |
||||
#define _SECP256K1_ECMULT_ |
||||
|
||||
#include "num.h" |
||||
#include "group.h" |
||||
|
||||
static void secp256k1_ecmult_start(void); |
||||
static void secp256k1_ecmult_stop(void); |
||||
|
||||
/** Double multiply: R = na*A + ng*G */ |
||||
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng); |
||||
|
||||
#endif |
@ -1,128 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ |
||||
#define _SECP256K1_ECMULT_GEN_IMPL_H_ |
||||
|
||||
#include "scalar.h" |
||||
#include "group.h" |
||||
#include "ecmult_gen.h" |
||||
|
||||
typedef struct { |
||||
/* For accelerating the computation of a*G:
|
||||
* To harden against timing attacks, use the following mechanism: |
||||
* * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. |
||||
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: |
||||
* * U_i = U * 2^i (for i=0..62) |
||||
* * U_i = U * (1-2^63) (for i=63) |
||||
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. |
||||
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is |
||||
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). |
||||
* None of the resulting prec group elements have a known scalar, and neither do any of |
||||
* the intermediate sums while computing a*G. |
||||
*/ |
||||
secp256k1_ge_storage_t prec[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ |
||||
} secp256k1_ecmult_gen_consts_t; |
||||
|
||||
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL; |
||||
|
||||
static void secp256k1_ecmult_gen_start(void) { |
||||
secp256k1_ge_t prec[1024]; |
||||
secp256k1_gej_t gj; |
||||
secp256k1_gej_t nums_gej; |
||||
secp256k1_ecmult_gen_consts_t *ret; |
||||
int i, j; |
||||
if (secp256k1_ecmult_gen_consts != NULL) { |
||||
return; |
||||
} |
||||
|
||||
/* Allocate the precomputation table. */ |
||||
ret = (secp256k1_ecmult_gen_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_gen_consts_t)); |
||||
|
||||
/* get the generator */ |
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); |
||||
|
||||
/* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ |
||||
{ |
||||
static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; |
||||
secp256k1_fe_t nums_x; |
||||
secp256k1_ge_t nums_ge; |
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&nums_x, nums_b32)); |
||||
VERIFY_CHECK(secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0)); |
||||
secp256k1_gej_set_ge(&nums_gej, &nums_ge); |
||||
/* Add G to make the bits in x uniformly distributed. */ |
||||
secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g); |
||||
} |
||||
|
||||
/* compute prec. */ |
||||
{ |
||||
secp256k1_gej_t precj[1024]; /* Jacobian versions of prec. */ |
||||
secp256k1_gej_t gbase; |
||||
secp256k1_gej_t numsbase; |
||||
gbase = gj; /* 16^j * G */ |
||||
numsbase = nums_gej; /* 2^j * nums. */ |
||||
for (j = 0; j < 64; j++) { |
||||
/* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ |
||||
precj[j*16] = numsbase; |
||||
for (i = 1; i < 16; i++) { |
||||
secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase); |
||||
} |
||||
/* Multiply gbase by 16. */ |
||||
for (i = 0; i < 4; i++) { |
||||
secp256k1_gej_double_var(&gbase, &gbase); |
||||
} |
||||
/* Multiply numbase by 2. */ |
||||
secp256k1_gej_double_var(&numsbase, &numsbase); |
||||
if (j == 62) { |
||||
/* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ |
||||
secp256k1_gej_neg(&numsbase, &numsbase); |
||||
secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej); |
||||
} |
||||
} |
||||
secp256k1_ge_set_all_gej_var(1024, prec, precj); |
||||
} |
||||
for (j = 0; j < 64; j++) { |
||||
for (i = 0; i < 16; i++) { |
||||
secp256k1_ge_to_storage(&ret->prec[j][i], &prec[j*16 + i]); |
||||
} |
||||
} |
||||
|
||||
/* Set the global pointer to the precomputation table. */ |
||||
secp256k1_ecmult_gen_consts = ret; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen_stop(void) { |
||||
secp256k1_ecmult_gen_consts_t *c; |
||||
if (secp256k1_ecmult_gen_consts == NULL) { |
||||
return; |
||||
} |
||||
|
||||
c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts; |
||||
secp256k1_ecmult_gen_consts = NULL; |
||||
free(c); |
||||
} |
||||
|
||||
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *gn) { |
||||
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts; |
||||
secp256k1_ge_t add; |
||||
secp256k1_ge_storage_t adds; |
||||
int bits; |
||||
int i, j; |
||||
secp256k1_gej_set_infinity(r); |
||||
add.infinity = 0; |
||||
for (j = 0; j < 64; j++) { |
||||
bits = secp256k1_scalar_get_bits(gn, j * 4, 4); |
||||
for (i = 0; i < 16; i++) { |
||||
secp256k1_ge_storage_cmov(&adds, &c->prec[j][i], i == bits); |
||||
} |
||||
secp256k1_ge_from_storage(&add, &adds); |
||||
secp256k1_gej_add_ge(r, r, &add); |
||||
} |
||||
bits = 0; |
||||
secp256k1_ge_clear(&add); |
||||
} |
||||
|
||||
#endif |
@ -1,302 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_ECMULT_IMPL_H_ |
||||
#define _SECP256K1_ECMULT_IMPL_H_ |
||||
|
||||
#include "group.h" |
||||
#include "scalar.h" |
||||
#include "ecmult.h" |
||||
|
||||
/* optimal for 128-bit and 256-bit exponents. */ |
||||
#define WINDOW_A 5 |
||||
|
||||
/** larger numbers may result in slightly better performance, at the cost of
|
||||
exponentially larger precomputed tables. */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Two tables for window size 15: 1.375 MiB. */ |
||||
#define WINDOW_G 15 |
||||
#else |
||||
/** One table for window size 16: 1.375 MiB. */ |
||||
#define WINDOW_G 16 |
||||
#endif |
||||
|
||||
/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
|
||||
* pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for |
||||
* 2^(w-2) entries. |
||||
* |
||||
* There are two versions of this function: |
||||
* - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation, |
||||
* fast to precompute, but slower to use in later additions. |
||||
* - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations, |
||||
* (much) slower to precompute, but a bit faster to use in later additions. |
||||
* To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as |
||||
* G is constant, so it only needs to be done once in advance. |
||||
*/ |
||||
static void secp256k1_ecmult_table_precomp_gej_var(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { |
||||
secp256k1_gej_t d; |
||||
int i; |
||||
pre[0] = *a; |
||||
secp256k1_gej_double_var(&d, &pre[0]); |
||||
for (i = 1; i < (1 << (w-2)); i++) { |
||||
secp256k1_gej_add_var(&pre[i], &d, &pre[i-1]); |
||||
} |
||||
} |
||||
|
||||
static void secp256k1_ecmult_table_precomp_ge_storage_var(secp256k1_ge_storage_t *pre, const secp256k1_gej_t *a, int w) { |
||||
secp256k1_gej_t d; |
||||
int i; |
||||
const int table_size = 1 << (w-2); |
||||
secp256k1_gej_t *prej = (secp256k1_gej_t *)checked_malloc(sizeof(secp256k1_gej_t) * table_size); |
||||
secp256k1_ge_t *prea = (secp256k1_ge_t *)checked_malloc(sizeof(secp256k1_ge_t) * table_size); |
||||
prej[0] = *a; |
||||
secp256k1_gej_double_var(&d, a); |
||||
for (i = 1; i < table_size; i++) { |
||||
secp256k1_gej_add_var(&prej[i], &d, &prej[i-1]); |
||||
} |
||||
secp256k1_ge_set_all_gej_var(table_size, prea, prej); |
||||
for (i = 0; i < table_size; i++) { |
||||
secp256k1_ge_to_storage(&pre[i], &prea[i]); |
||||
} |
||||
free(prej); |
||||
free(prea); |
||||
} |
||||
|
||||
/** The number of entries a table with precomputed multiples needs to have. */ |
||||
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) |
||||
|
||||
/** The following two macro retrieves a particular odd multiple from a table
|
||||
* of precomputed multiples. */ |
||||
#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) do { \ |
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
*(r) = (pre)[((n)-1)/2]; \
|
||||
} else { \
|
||||
secp256k1_gej_neg((r), &(pre)[(-(n)-1)/2]); \
|
||||
} \
|
||||
} while(0) |
||||
#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ |
||||
VERIFY_CHECK(((n) & 1) == 1); \
|
||||
VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
|
||||
VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
|
||||
if ((n) > 0) { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
|
||||
} else { \
|
||||
secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
|
||||
secp256k1_ge_neg((r), (r)); \
|
||||
} \
|
||||
} while(0) |
||||
|
||||
typedef struct { |
||||
/* For accelerating the computation of a*P + b*G: */ |
||||
secp256k1_ge_storage_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */ |
||||
#ifdef USE_ENDOMORPHISM |
||||
secp256k1_ge_storage_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */ |
||||
#endif |
||||
} secp256k1_ecmult_consts_t; |
||||
|
||||
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; |
||||
|
||||
static void secp256k1_ecmult_start(void) { |
||||
secp256k1_gej_t gj; |
||||
secp256k1_ecmult_consts_t *ret; |
||||
if (secp256k1_ecmult_consts != NULL) { |
||||
return; |
||||
} |
||||
|
||||
/* Allocate the precomputation table. */ |
||||
ret = (secp256k1_ecmult_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_consts_t)); |
||||
|
||||
/* get the generator */ |
||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); |
||||
|
||||
|
||||
/* precompute the tables with odd multiples */ |
||||
secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g, &gj, WINDOW_G); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
{ |
||||
secp256k1_gej_t g_128j; |
||||
int i; |
||||
/* calculate 2^128*generator */ |
||||
g_128j = gj; |
||||
for (i = 0; i < 128; i++) { |
||||
secp256k1_gej_double_var(&g_128j, &g_128j); |
||||
} |
||||
secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g_128, &g_128j, WINDOW_G); |
||||
} |
||||
#endif |
||||
|
||||
/* Set the global pointer to the precomputation table. */ |
||||
secp256k1_ecmult_consts = ret; |
||||
} |
||||
|
||||
static void secp256k1_ecmult_stop(void) { |
||||
secp256k1_ecmult_consts_t *c; |
||||
if (secp256k1_ecmult_consts == NULL) { |
||||
return; |
||||
} |
||||
|
||||
c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; |
||||
secp256k1_ecmult_consts = NULL; |
||||
free(c); |
||||
} |
||||
|
||||
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
|
||||
* with the following guarantees: |
||||
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) |
||||
* - two non-zero entries in wnaf are separated by at least w-1 zeroes. |
||||
* - the number of set values in wnaf is returned. This number is at most 256, and at most one more |
||||
* - than the number of bits in the (absolute value) of the input. |
||||
*/ |
||||
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) { |
||||
secp256k1_scalar_t s = *a; |
||||
int set_bits = 0; |
||||
int bit = 0; |
||||
int sign = 1; |
||||
|
||||
if (secp256k1_scalar_get_bits(&s, 255, 1)) { |
||||
secp256k1_scalar_negate(&s, &s); |
||||
sign = -1; |
||||
} |
||||
|
||||
while (bit < 256) { |
||||
int now; |
||||
int word; |
||||
if (secp256k1_scalar_get_bits(&s, bit, 1) == 0) { |
||||
bit++; |
||||
continue; |
||||
} |
||||
while (set_bits < bit) { |
||||
wnaf[set_bits++] = 0; |
||||
} |
||||
now = w; |
||||
if (bit + now > 256) { |
||||
now = 256 - bit; |
||||
} |
||||
word = secp256k1_scalar_get_bits_var(&s, bit, now); |
||||
if (word & (1 << (w-1))) { |
||||
secp256k1_scalar_add_bit(&s, bit + w); |
||||
wnaf[set_bits++] = sign * (word - (1 << w)); |
||||
} else { |
||||
wnaf[set_bits++] = sign * word; |
||||
} |
||||
bit += now; |
||||
} |
||||
return set_bits; |
||||
} |
||||
|
||||
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) { |
||||
secp256k1_gej_t tmpj; |
||||
secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_ge_t tmpa; |
||||
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; |
||||
#ifdef USE_ENDOMORPHISM |
||||
secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
secp256k1_scalar_t na_1, na_lam; |
||||
/* Splitted G factors. */ |
||||
secp256k1_scalar_t ng_1, ng_128; |
||||
int wnaf_na_1[130]; |
||||
int wnaf_na_lam[130]; |
||||
int bits_na_1; |
||||
int bits_na_lam; |
||||
int wnaf_ng_1[129]; |
||||
int bits_ng_1; |
||||
int wnaf_ng_128[129]; |
||||
int bits_ng_128; |
||||
#else |
||||
int wnaf_na[256]; |
||||
int bits_na; |
||||
int wnaf_ng[257]; |
||||
int bits_ng; |
||||
#endif |
||||
int i; |
||||
int bits; |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ |
||||
secp256k1_scalar_split_lambda_var(&na_1, &na_lam, na); |
||||
|
||||
/* build wnaf representation for na_1 and na_lam. */ |
||||
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); |
||||
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); |
||||
VERIFY_CHECK(bits_na_1 <= 130); |
||||
VERIFY_CHECK(bits_na_lam <= 130); |
||||
bits = bits_na_1; |
||||
if (bits_na_lam > bits) { |
||||
bits = bits_na_lam; |
||||
} |
||||
#else |
||||
/* build wnaf representation for na. */ |
||||
bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); |
||||
bits = bits_na; |
||||
#endif |
||||
|
||||
/* calculate odd multiples of a */ |
||||
secp256k1_ecmult_table_precomp_gej_var(pre_a, a, WINDOW_A); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { |
||||
secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]); |
||||
} |
||||
|
||||
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ |
||||
secp256k1_scalar_split_128(&ng_1, &ng_128, ng); |
||||
|
||||
/* Build wnaf representation for ng_1 and ng_128 */ |
||||
bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); |
||||
bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); |
||||
if (bits_ng_1 > bits) { |
||||
bits = bits_ng_1; |
||||
} |
||||
if (bits_ng_128 > bits) { |
||||
bits = bits_ng_128; |
||||
} |
||||
#else |
||||
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, ng, WINDOW_G); |
||||
if (bits_ng > bits) { |
||||
bits = bits_ng; |
||||
} |
||||
#endif |
||||
|
||||
secp256k1_gej_set_infinity(r); |
||||
|
||||
for (i = bits-1; i >= 0; i--) { |
||||
int n; |
||||
secp256k1_gej_double_var(r, r); |
||||
#ifdef USE_ENDOMORPHISM |
||||
if (i < bits_na_1 && (n = wnaf_na_1[i])) { |
||||
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); |
||||
secp256k1_gej_add_var(r, r, &tmpj); |
||||
} |
||||
if (i < bits_na_lam && (n = wnaf_na_lam[i])) { |
||||
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); |
||||
secp256k1_gej_add_var(r, r, &tmpj); |
||||
} |
||||
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa); |
||||
} |
||||
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g_128, n, WINDOW_G); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa); |
||||
} |
||||
#else |
||||
if (i < bits_na && (n = wnaf_na[i])) { |
||||
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); |
||||
secp256k1_gej_add_var(r, r, &tmpj); |
||||
} |
||||
if (i < bits_ng && (n = wnaf_ng[i])) { |
||||
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G); |
||||
secp256k1_gej_add_ge_var(r, r, &tmpa); |
||||
} |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,118 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_GROUP_ |
||||
#define _SECP256K1_GROUP_ |
||||
|
||||
#include "num.h" |
||||
#include "field.h" |
||||
|
||||
/** A group element of the secp256k1 curve, in affine coordinates. */ |
||||
typedef struct { |
||||
secp256k1_fe_t x; |
||||
secp256k1_fe_t y; |
||||
int infinity; /* whether this represents the point at infinity */ |
||||
} secp256k1_ge_t; |
||||
|
||||
#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} |
||||
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} |
||||
|
||||
/** A group element of the secp256k1 curve, in jacobian coordinates. */ |
||||
typedef struct { |
||||
secp256k1_fe_t x; /* actual X: x/z^2 */ |
||||
secp256k1_fe_t y; /* actual Y: y/z^3 */ |
||||
secp256k1_fe_t z; |
||||
int infinity; /* whether this represents the point at infinity */ |
||||
} secp256k1_gej_t; |
||||
|
||||
#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} |
||||
#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} |
||||
|
||||
typedef struct { |
||||
secp256k1_fe_storage_t x; |
||||
secp256k1_fe_storage_t y; |
||||
} secp256k1_ge_storage_t; |
||||
|
||||
#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} |
||||
|
||||
/** Set a group element equal to the point at infinity */ |
||||
static void secp256k1_ge_set_infinity(secp256k1_ge_t *r); |
||||
|
||||
/** Set a group element equal to the point with given X and Y coordinates */ |
||||
static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); |
||||
|
||||
/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness
|
||||
* for Y. Return value indicates whether the result is valid. */ |
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd); |
||||
|
||||
/** Check whether a group element is the point at infinity. */ |
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a); |
||||
|
||||
/** Check whether a group element is valid (i.e., on the curve). */ |
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a); |
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a); |
||||
|
||||
/** Set a group element equal to another which is given in jacobian coordinates */ |
||||
static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); |
||||
|
||||
/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ |
||||
static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a); |
||||
|
||||
|
||||
/** Set a group element (jacobian) equal to the point at infinity. */ |
||||
static void secp256k1_gej_set_infinity(secp256k1_gej_t *r); |
||||
|
||||
/** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ |
||||
static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); |
||||
|
||||
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ |
||||
static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); |
||||
|
||||
/** Compare the X coordinate of a group element (jacobian). */ |
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a); |
||||
|
||||
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ |
||||
static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
|
||||
/** Check whether a group element is the point at infinity. */ |
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a); |
||||
|
||||
/** Set r equal to the double of a. */ |
||||
static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
|
||||
/** Set r equal to the sum of a and b. */ |
||||
static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b); |
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ |
||||
static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); |
||||
|
||||
/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient
|
||||
than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time |
||||
guarantee, and b is allowed to be infinity. */ |
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ |
||||
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
#endif |
||||
|
||||
/** Clear a secp256k1_gej_t to prevent leaking sensitive information. */ |
||||
static void secp256k1_gej_clear(secp256k1_gej_t *r); |
||||
|
||||
/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */ |
||||
static void secp256k1_ge_clear(secp256k1_ge_t *r); |
||||
|
||||
/** Convert a group element to the storage type. */ |
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage_t *r, const secp256k1_ge_t*); |
||||
|
||||
/** Convert a group element back from the storage type. */ |
||||
static void secp256k1_ge_from_storage(secp256k1_ge_t *r, const secp256k1_ge_storage_t*); |
||||
|
||||
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ |
||||
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage_t *r, const secp256k1_ge_storage_t *a, int flag); |
||||
|
||||
#endif |
@ -1,434 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_GROUP_IMPL_H_ |
||||
#define _SECP256K1_GROUP_IMPL_H_ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "num.h" |
||||
#include "field.h" |
||||
#include "group.h" |
||||
|
||||
/** Generator for secp256k1, value 'g' defined in
|
||||
* "Standards for Efficient Cryptography" (SEC2) 2.7.1. |
||||
*/ |
||||
static const secp256k1_ge_t secp256k1_ge_const_g = SECP256K1_GE_CONST( |
||||
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, |
||||
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, |
||||
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, |
||||
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL |
||||
); |
||||
|
||||
static void secp256k1_ge_set_infinity(secp256k1_ge_t *r) { |
||||
r->infinity = 1; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { |
||||
r->infinity = 0; |
||||
r->x = *x; |
||||
r->y = *y; |
||||
} |
||||
|
||||
static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a) { |
||||
return a->infinity; |
||||
} |
||||
|
||||
static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) { |
||||
*r = *a; |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
|
||||
static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { |
||||
secp256k1_fe_t z2, z3; |
||||
r->infinity = a->infinity; |
||||
secp256k1_fe_inv(&a->z, &a->z); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_mul(&z3, &a->z, &z2); |
||||
secp256k1_fe_mul(&a->x, &a->x, &z2); |
||||
secp256k1_fe_mul(&a->y, &a->y, &z3); |
||||
secp256k1_fe_set_int(&a->z, 1); |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_gej_var(secp256k1_ge_t *r, secp256k1_gej_t *a) { |
||||
secp256k1_fe_t z2, z3; |
||||
r->infinity = a->infinity; |
||||
if (a->infinity) { |
||||
return; |
||||
} |
||||
secp256k1_fe_inv_var(&a->z, &a->z); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_mul(&z3, &a->z, &z2); |
||||
secp256k1_fe_mul(&a->x, &a->x, &z2); |
||||
secp256k1_fe_mul(&a->y, &a->y, &z3); |
||||
secp256k1_fe_set_int(&a->z, 1); |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
} |
||||
|
||||
static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t *r, const secp256k1_gej_t *a) { |
||||
secp256k1_fe_t *az; |
||||
secp256k1_fe_t *azi; |
||||
size_t i; |
||||
size_t count = 0; |
||||
az = (secp256k1_fe_t *)checked_malloc(sizeof(secp256k1_fe_t) * len); |
||||
for (i = 0; i < len; i++) { |
||||
if (!a[i].infinity) { |
||||
az[count++] = a[i].z; |
||||
} |
||||
} |
||||
|
||||
azi = (secp256k1_fe_t *)checked_malloc(sizeof(secp256k1_fe_t) * count); |
||||
secp256k1_fe_inv_all_var(count, azi, az); |
||||
free(az); |
||||
|
||||
count = 0; |
||||
for (i = 0; i < len; i++) { |
||||
r[i].infinity = a[i].infinity; |
||||
if (!a[i].infinity) { |
||||
secp256k1_fe_t zi2, zi3; |
||||
secp256k1_fe_t *zi = &azi[count++]; |
||||
secp256k1_fe_sqr(&zi2, zi); |
||||
secp256k1_fe_mul(&zi3, &zi2, zi); |
||||
secp256k1_fe_mul(&r[i].x, &a[i].x, &zi2); |
||||
secp256k1_fe_mul(&r[i].y, &a[i].y, &zi3); |
||||
} |
||||
} |
||||
free(azi); |
||||
} |
||||
|
||||
static void secp256k1_gej_set_infinity(secp256k1_gej_t *r) { |
||||
r->infinity = 1; |
||||
secp256k1_fe_set_int(&r->x, 0); |
||||
secp256k1_fe_set_int(&r->y, 0); |
||||
secp256k1_fe_set_int(&r->z, 0); |
||||
} |
||||
|
||||
static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { |
||||
r->infinity = 0; |
||||
r->x = *x; |
||||
r->y = *y; |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
} |
||||
|
||||
static void secp256k1_gej_clear(secp256k1_gej_t *r) { |
||||
r->infinity = 0; |
||||
secp256k1_fe_clear(&r->x); |
||||
secp256k1_fe_clear(&r->y); |
||||
secp256k1_fe_clear(&r->z); |
||||
} |
||||
|
||||
static void secp256k1_ge_clear(secp256k1_ge_t *r) { |
||||
r->infinity = 0; |
||||
secp256k1_fe_clear(&r->x); |
||||
secp256k1_fe_clear(&r->y); |
||||
} |
||||
|
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) { |
||||
secp256k1_fe_t x2, x3, c; |
||||
r->x = *x; |
||||
secp256k1_fe_sqr(&x2, x); |
||||
secp256k1_fe_mul(&x3, x, &x2); |
||||
r->infinity = 0; |
||||
secp256k1_fe_set_int(&c, 7); |
||||
secp256k1_fe_add(&c, &x3); |
||||
if (!secp256k1_fe_sqrt_var(&r->y, &c)) { |
||||
return 0; |
||||
} |
||||
secp256k1_fe_normalize_var(&r->y); |
||||
if (secp256k1_fe_is_odd(&r->y) != odd) { |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) { |
||||
r->infinity = a->infinity; |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
} |
||||
|
||||
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a) { |
||||
secp256k1_fe_t r, r2; |
||||
VERIFY_CHECK(!a->infinity); |
||||
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); |
||||
r2 = a->x; secp256k1_fe_normalize_weak(&r2); |
||||
return secp256k1_fe_equal_var(&r, &r2); |
||||
} |
||||
|
||||
static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a) { |
||||
r->infinity = a->infinity; |
||||
r->x = a->x; |
||||
r->y = a->y; |
||||
r->z = a->z; |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
} |
||||
|
||||
static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a) { |
||||
return a->infinity; |
||||
} |
||||
|
||||
static int secp256k1_gej_is_valid_var(const secp256k1_gej_t *a) { |
||||
secp256k1_fe_t y2, x3, z2, z6; |
||||
if (a->infinity) { |
||||
return 0; |
||||
} |
||||
/** y^2 = x^3 + 7
|
||||
* (Y/Z^3)^2 = (X/Z^2)^3 + 7 |
||||
* Y^2 / Z^6 = X^3 / Z^6 + 7 |
||||
* Y^2 = X^3 + 7*Z^6 |
||||
*/ |
||||
secp256k1_fe_sqr(&y2, &a->y); |
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
secp256k1_fe_sqr(&z2, &a->z); |
||||
secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); |
||||
secp256k1_fe_mul_int(&z6, 7); |
||||
secp256k1_fe_add(&x3, &z6); |
||||
secp256k1_fe_normalize_weak(&x3); |
||||
return secp256k1_fe_equal_var(&y2, &x3); |
||||
} |
||||
|
||||
static int secp256k1_ge_is_valid_var(const secp256k1_ge_t *a) { |
||||
secp256k1_fe_t y2, x3, c; |
||||
if (a->infinity) { |
||||
return 0; |
||||
} |
||||
/* y^2 = x^3 + 7 */ |
||||
secp256k1_fe_sqr(&y2, &a->y); |
||||
secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
secp256k1_fe_set_int(&c, 7); |
||||
secp256k1_fe_add(&x3, &c); |
||||
secp256k1_fe_normalize_weak(&x3); |
||||
return secp256k1_fe_equal_var(&y2, &x3); |
||||
} |
||||
|
||||
static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) { |
||||
/* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe_t t1,t2,t3,t4; |
||||
/** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
|
||||
* Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have |
||||
* y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. |
||||
*/ |
||||
r->infinity = a->infinity; |
||||
if (r->infinity) { |
||||
return; |
||||
} |
||||
|
||||
secp256k1_fe_mul(&r->z, &a->z, &a->y); |
||||
secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ |
||||
secp256k1_fe_sqr(&t1, &a->x); |
||||
secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ |
||||
secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ |
||||
secp256k1_fe_sqr(&t3, &a->y); |
||||
secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ |
||||
secp256k1_fe_sqr(&t4, &t3); |
||||
secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ |
||||
secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ |
||||
r->x = t3; |
||||
secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ |
||||
secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ |
||||
secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ |
||||
secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ |
||||
secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ |
||||
secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ |
||||
secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ |
||||
secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ |
||||
secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ |
||||
} |
||||
|
||||
static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { |
||||
/* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe_t z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; |
||||
if (a->infinity) { |
||||
*r = *b; |
||||
return; |
||||
} |
||||
if (b->infinity) { |
||||
*r = *a; |
||||
return; |
||||
} |
||||
r->infinity = 0; |
||||
secp256k1_fe_sqr(&z22, &b->z); |
||||
secp256k1_fe_sqr(&z12, &a->z); |
||||
secp256k1_fe_mul(&u1, &a->x, &z22); |
||||
secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); |
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) { |
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) { |
||||
secp256k1_gej_double_var(r, a); |
||||
} else { |
||||
r->infinity = 1; |
||||
} |
||||
return; |
||||
} |
||||
secp256k1_fe_sqr(&i2, &i); |
||||
secp256k1_fe_sqr(&h2, &h); |
||||
secp256k1_fe_mul(&h3, &h, &h2); |
||||
secp256k1_fe_mul(&r->z, &a->z, &b->z); secp256k1_fe_mul(&r->z, &r->z, &h); |
||||
secp256k1_fe_mul(&t, &u1, &h2); |
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); |
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); |
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); |
||||
secp256k1_fe_add(&r->y, &h3); |
||||
} |
||||
|
||||
static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { |
||||
/* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ |
||||
secp256k1_fe_t z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; |
||||
if (a->infinity) { |
||||
r->infinity = b->infinity; |
||||
r->x = b->x; |
||||
r->y = b->y; |
||||
secp256k1_fe_set_int(&r->z, 1); |
||||
return; |
||||
} |
||||
if (b->infinity) { |
||||
*r = *a; |
||||
return; |
||||
} |
||||
r->infinity = 0; |
||||
secp256k1_fe_sqr(&z12, &a->z); |
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); |
||||
secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); |
||||
secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
if (secp256k1_fe_normalizes_to_zero_var(&h)) { |
||||
if (secp256k1_fe_normalizes_to_zero_var(&i)) { |
||||
secp256k1_gej_double_var(r, a); |
||||
} else { |
||||
r->infinity = 1; |
||||
} |
||||
return; |
||||
} |
||||
secp256k1_fe_sqr(&i2, &i); |
||||
secp256k1_fe_sqr(&h2, &h); |
||||
secp256k1_fe_mul(&h3, &h, &h2); |
||||
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); |
||||
secp256k1_fe_mul(&t, &u1, &h2); |
||||
r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); |
||||
secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); |
||||
secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); |
||||
secp256k1_fe_add(&r->y, &h3); |
||||
} |
||||
|
||||
static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { |
||||
/* Operations: 7 mul, 5 sqr, 5 normalize, 19 mul_int/add/negate */ |
||||
secp256k1_fe_t zz, u1, u2, s1, s2, z, t, m, n, q, rr; |
||||
int infinity; |
||||
VERIFY_CHECK(!b->infinity); |
||||
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); |
||||
|
||||
/** In:
|
||||
* Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. |
||||
* In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. |
||||
* we find as solution for a unified addition/doubling formula: |
||||
* lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. |
||||
* x3 = lambda^2 - (x1 + x2) |
||||
* 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). |
||||
* |
||||
* Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: |
||||
* U1 = X1*Z2^2, U2 = X2*Z1^2 |
||||
* S1 = Y1*Z2^3, S2 = Y2*Z1^3 |
||||
* Z = Z1*Z2 |
||||
* T = U1+U2 |
||||
* M = S1+S2 |
||||
* Q = T*M^2 |
||||
* R = T^2-U1*U2 |
||||
* X3 = 4*(R^2-Q) |
||||
* Y3 = 4*(R*(3*Q-2*R^2)-M^4) |
||||
* Z3 = 2*M*Z |
||||
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) |
||||
*/ |
||||
|
||||
secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ |
||||
u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ |
||||
secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ |
||||
s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ |
||||
secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */ |
||||
secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ |
||||
z = a->z; /* z = Z = Z1*Z2 (8) */ |
||||
t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ |
||||
m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ |
||||
secp256k1_fe_sqr(&n, &m); /* n = M^2 (1) */ |
||||
secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*M^2 (1) */ |
||||
secp256k1_fe_sqr(&n, &n); /* n = M^4 (1) */ |
||||
secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ |
||||
secp256k1_fe_mul(&t, &u1, &u2); secp256k1_fe_negate(&t, &t, 1); /* t = -U1*U2 (2) */ |
||||
secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */ |
||||
secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */ |
||||
secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */ |
||||
infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); |
||||
secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */ |
||||
r->x = t; /* r->x = R^2 (1) */ |
||||
secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ |
||||
secp256k1_fe_add(&r->x, &q); /* r->x = R^2-Q (3) */ |
||||
secp256k1_fe_normalize(&r->x); |
||||
secp256k1_fe_mul_int(&q, 3); /* q = -3*Q (6) */ |
||||
secp256k1_fe_mul_int(&t, 2); /* t = 2*R^2 (2) */ |
||||
secp256k1_fe_add(&t, &q); /* t = 2*R^2-3*Q (8) */ |
||||
secp256k1_fe_mul(&t, &t, &rr); /* t = R*(2*R^2-3*Q) (1) */ |
||||
secp256k1_fe_add(&t, &n); /* t = R*(2*R^2-3*Q)+M^4 (2) */ |
||||
secp256k1_fe_negate(&r->y, &t, 2); /* r->y = R*(3*Q-2*R^2)-M^4 (3) */ |
||||
secp256k1_fe_normalize_weak(&r->y); |
||||
secp256k1_fe_mul_int(&r->x, 4 * (1 - a->infinity)); /* r->x = X3 = 4*(R^2-Q) */ |
||||
secp256k1_fe_mul_int(&r->y, 4 * (1 - a->infinity)); /* r->y = Y3 = 4*R*(3*Q-2*R^2)-4*M^4 (4) */ |
||||
|
||||
/** In case a->infinity == 1, the above code results in r->x, r->y, and r->z all equal to 0.
|
||||
* Add b->x to x, b->y to y, and 1 to z in that case. |
||||
*/ |
||||
t = b->x; secp256k1_fe_mul_int(&t, a->infinity); |
||||
secp256k1_fe_add(&r->x, &t); |
||||
t = b->y; secp256k1_fe_mul_int(&t, a->infinity); |
||||
secp256k1_fe_add(&r->y, &t); |
||||
secp256k1_fe_set_int(&t, a->infinity); |
||||
secp256k1_fe_add(&r->z, &t); |
||||
r->infinity = infinity; |
||||
} |
||||
|
||||
static void secp256k1_ge_to_storage(secp256k1_ge_storage_t *r, const secp256k1_ge_t *a) { |
||||
secp256k1_fe_t x, y; |
||||
VERIFY_CHECK(!a->infinity); |
||||
x = a->x; |
||||
secp256k1_fe_normalize(&x); |
||||
y = a->y; |
||||
secp256k1_fe_normalize(&y); |
||||
secp256k1_fe_to_storage(&r->x, &x); |
||||
secp256k1_fe_to_storage(&r->y, &y); |
||||
} |
||||
|
||||
static void secp256k1_ge_from_storage(secp256k1_ge_t *r, const secp256k1_ge_storage_t *a) { |
||||
secp256k1_fe_from_storage(&r->x, &a->x); |
||||
secp256k1_fe_from_storage(&r->y, &a->y); |
||||
r->infinity = 0; |
||||
} |
||||
|
||||
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage_t *r, const secp256k1_ge_storage_t *a, int flag) { |
||||
secp256k1_fe_storage_cmov(&r->x, &a->x, flag); |
||||
secp256k1_fe_storage_cmov(&r->y, &a->y, flag); |
||||
} |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) { |
||||
static const secp256k1_fe_t beta = SECP256K1_FE_CONST( |
||||
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, |
||||
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul |
||||
); |
||||
*r = *a; |
||||
secp256k1_fe_mul(&r->x, &r->x, &beta); |
||||
} |
||||
#endif |
||||
|
||||
#endif |
@ -1,93 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#ifndef _SECP256K1_SCALAR_ |
||||
#define _SECP256K1_SCALAR_ |
||||
|
||||
#include "num.h" |
||||
|
||||
#if defined HAVE_CONFIG_H |
||||
#include "libsecp256k1-config.h" |
||||
#endif |
||||
|
||||
#if defined(USE_SCALAR_4X64) |
||||
#include "scalar_4x64.h" |
||||
#elif defined(USE_SCALAR_8X32) |
||||
#include "scalar_8x32.h" |
||||
#else |
||||
#error "Please select scalar implementation" |
||||
#endif |
||||
|
||||
/** Clear a scalar to prevent the leak of sensitive data. */ |
||||
static void secp256k1_scalar_clear(secp256k1_scalar_t *r); |
||||
|
||||
/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ |
||||
static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count); |
||||
|
||||
/** Access bits from a scalar. Not constant time. */ |
||||
static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar_t *a, unsigned int offset, unsigned int count); |
||||
|
||||
/** Set a scalar from a big endian byte array. */ |
||||
static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow); |
||||
|
||||
/** Set a scalar to an unsigned integer. */ |
||||
static void secp256k1_scalar_set_int(secp256k1_scalar_t *r, unsigned int v); |
||||
|
||||
/** Convert a scalar to a byte array. */ |
||||
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a); |
||||
|
||||
/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ |
||||
static int secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); |
||||
|
||||
/** Add a power of two to a scalar. The result is not allowed to overflow. */ |
||||
static void secp256k1_scalar_add_bit(secp256k1_scalar_t *r, unsigned int bit); |
||||
|
||||
/** Multiply two scalars (modulo the group order). */ |
||||
static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); |
||||
|
||||
/** Compute the square of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); |
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); |
||||
|
||||
/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ |
||||
static void secp256k1_scalar_inverse_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); |
||||
|
||||
/** Compute the complement of a scalar (modulo the group order). */ |
||||
static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); |
||||
|
||||
/** Check whether a scalar equals zero. */ |
||||
static int secp256k1_scalar_is_zero(const secp256k1_scalar_t *a); |
||||
|
||||
/** Check whether a scalar equals one. */ |
||||
static int secp256k1_scalar_is_one(const secp256k1_scalar_t *a); |
||||
|
||||
/** Check whether a scalar is higher than the group order divided by 2. */ |
||||
static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a); |
||||
|
||||
#ifndef USE_NUM_NONE |
||||
/** Convert a scalar to a number. */ |
||||
static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a); |
||||
|
||||
/** Get the order of the group as a number. */ |
||||
static void secp256k1_scalar_order_get_num(secp256k1_num_t *r); |
||||
#endif |
||||
|
||||
/** Compare two scalars. */ |
||||
static int secp256k1_scalar_eq(const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); |
||||
|
||||
#ifdef USE_ENDOMORPHISM |
||||
/** Find r1 and r2 such that r1+r2*2^128 = a. */ |
||||
static void secp256k1_scalar_split_128(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a); |
||||
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ |
||||
static void secp256k1_scalar_split_lambda_var(secp256k1_scalar_t *r1, secp256k1_scalar_t *r2, const secp256k1_scalar_t *a); |
||||
#endif |
||||
|
||||
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ |
||||
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b, unsigned int shift); |
||||
|
||||
#endif |
@ -1,372 +0,0 @@ |
||||
/**********************************************************************
|
||||
* Copyright (c) 2013, 2014 Pieter Wuille * |
||||
* Distributed under the MIT software license, see the accompanying * |
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||
**********************************************************************/ |
||||
|
||||
#define SECP256K1_BUILD (1) |
||||
|
||||
#include "include/secp256k1.h" |
||||
|
||||
#include "util.h" |
||||
#include "num_impl.h" |
||||
#include "field_impl.h" |
||||
#include "scalar_impl.h" |
||||
#include "group_impl.h" |
||||
#include "ecmult_impl.h" |
||||
#include "ecmult_gen_impl.h" |
||||
#include "ecdsa_impl.h" |
||||
#include "eckey_impl.h" |
||||
#include "hash_impl.h" |
||||
|
||||
void secp256k1_start(unsigned int flags) { |
||||
if (flags & SECP256K1_START_SIGN) { |
||||
secp256k1_ecmult_gen_start(); |
||||
} |
||||
if (flags & SECP256K1_START_VERIFY) { |
||||
secp256k1_ecmult_start(); |
||||
} |
||||
} |
||||
|
||||
void secp256k1_stop(void) { |
||||
secp256k1_ecmult_stop(); |
||||
secp256k1_ecmult_gen_stop(); |
||||
} |
||||
|
||||
int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) { |
||||
secp256k1_ge_t q; |
||||
secp256k1_ecdsa_sig_t s; |
||||
secp256k1_scalar_t m; |
||||
int ret = -3; |
||||
DEBUG_CHECK(secp256k1_ecmult_consts != NULL); |
||||
DEBUG_CHECK(msg32 != NULL); |
||||
DEBUG_CHECK(sig != NULL); |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL); |
||||
|
||||
if (secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) { |
||||
if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { |
||||
if (secp256k1_ecdsa_sig_verify(&s, &q, &m)) { |
||||
/* success is 1, all other values are fail */ |
||||
ret = 1; |
||||
} else { |
||||
ret = 0; |
||||
} |
||||
} else { |
||||
ret = -2; |
||||
} |
||||
} else { |
||||
ret = -1; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { |
||||
secp256k1_rfc6979_hmac_sha256_t rng; |
||||
unsigned int i; |
||||
secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32, (const unsigned char*)data, data != NULL ? 32 : 0); |
||||
for (i = 0; i <= counter; i++) { |
||||
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); |
||||
} |
||||
secp256k1_rfc6979_hmac_sha256_finalize(&rng); |
||||
return 1; |
||||
} |
||||
|
||||
const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; |
||||
const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979; |
||||
|
||||
int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { |
||||
secp256k1_ecdsa_sig_t sig; |
||||
secp256k1_scalar_t sec, non, msg; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
unsigned int count = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); |
||||
DEBUG_CHECK(msg32 != NULL); |
||||
DEBUG_CHECK(signature != NULL); |
||||
DEBUG_CHECK(signaturelen != NULL); |
||||
DEBUG_CHECK(seckey != NULL); |
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
/* Fail if the secret key is invalid. */ |
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) { |
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL); |
||||
while (1) { |
||||
unsigned char nonce32[32]; |
||||
ret = noncefp(nonce32, msg32, seckey, count, noncedata); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
||||
memset(nonce32, 0, 32); |
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) { |
||||
if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) { |
||||
break; |
||||
} |
||||
} |
||||
count++; |
||||
} |
||||
if (ret) { |
||||
ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); |
||||
} |
||||
secp256k1_scalar_clear(&msg); |
||||
secp256k1_scalar_clear(&non); |
||||
secp256k1_scalar_clear(&sec); |
||||
} |
||||
if (!ret) { |
||||
*signaturelen = 0; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) { |
||||
secp256k1_ecdsa_sig_t sig; |
||||
secp256k1_scalar_t sec, non, msg; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
unsigned int count = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); |
||||
DEBUG_CHECK(msg32 != NULL); |
||||
DEBUG_CHECK(sig64 != NULL); |
||||
DEBUG_CHECK(seckey != NULL); |
||||
if (noncefp == NULL) { |
||||
noncefp = secp256k1_nonce_function_default; |
||||
} |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
/* Fail if the secret key is invalid. */ |
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) { |
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL); |
||||
while (1) { |
||||
unsigned char nonce32[32]; |
||||
ret = noncefp(nonce32, msg32, seckey, count, noncedata); |
||||
if (!ret) { |
||||
break; |
||||
} |
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow); |
||||
memset(nonce32, 0, 32); |
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) { |
||||
if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) { |
||||
break; |
||||
} |
||||
} |
||||
count++; |
||||
} |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(sig64, &sig.r); |
||||
secp256k1_scalar_get_b32(sig64 + 32, &sig.s); |
||||
} |
||||
secp256k1_scalar_clear(&msg); |
||||
secp256k1_scalar_clear(&non); |
||||
secp256k1_scalar_clear(&sec); |
||||
} |
||||
if (!ret) { |
||||
memset(sig64, 0, 64); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) { |
||||
secp256k1_ge_t q; |
||||
secp256k1_ecdsa_sig_t sig; |
||||
secp256k1_scalar_t m; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_consts != NULL); |
||||
DEBUG_CHECK(msg32 != NULL); |
||||
DEBUG_CHECK(sig64 != NULL); |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
DEBUG_CHECK(pubkeylen != NULL); |
||||
DEBUG_CHECK(recid >= 0 && recid <= 3); |
||||
|
||||
secp256k1_scalar_set_b32(&sig.r, sig64, &overflow); |
||||
if (!overflow) { |
||||
secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow); |
||||
if (!overflow) { |
||||
secp256k1_scalar_set_b32(&m, msg32, NULL); |
||||
|
||||
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { |
||||
ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed); |
||||
} |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_seckey_verify(const unsigned char *seckey) { |
||||
secp256k1_scalar_t sec; |
||||
int ret; |
||||
int overflow; |
||||
DEBUG_CHECK(seckey != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
ret = !secp256k1_scalar_is_zero(&sec) && !overflow; |
||||
secp256k1_scalar_clear(&sec); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { |
||||
secp256k1_ge_t q; |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
|
||||
return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen); |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { |
||||
secp256k1_gej_t pj; |
||||
secp256k1_ge_t p; |
||||
secp256k1_scalar_t sec; |
||||
int overflow; |
||||
int ret = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
DEBUG_CHECK(pubkeylen != NULL); |
||||
DEBUG_CHECK(seckey != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow); |
||||
if (!overflow) { |
||||
secp256k1_ecmult_gen(&pj, &sec); |
||||
secp256k1_scalar_clear(&sec); |
||||
secp256k1_ge_set_gej(&p, &pj); |
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed); |
||||
} |
||||
if (!ret) { |
||||
*pubkeylen = 0; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { |
||||
secp256k1_ge_t p; |
||||
int ret = 0; |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
DEBUG_CHECK(pubkeylen != NULL); |
||||
|
||||
if (secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen)) { |
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { |
||||
secp256k1_scalar_t term; |
||||
secp256k1_scalar_t sec; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
DEBUG_CHECK(seckey != NULL); |
||||
DEBUG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); |
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); |
||||
|
||||
ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow; |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &sec); |
||||
} |
||||
|
||||
secp256k1_scalar_clear(&sec); |
||||
secp256k1_scalar_clear(&term); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { |
||||
secp256k1_ge_t p; |
||||
secp256k1_scalar_t term; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_consts != NULL); |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
DEBUG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow); |
||||
if (!overflow) { |
||||
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); |
||||
if (ret) { |
||||
ret = secp256k1_eckey_pubkey_tweak_add(&p, &term); |
||||
} |
||||
if (ret) { |
||||
int oldlen = pubkeylen; |
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); |
||||
VERIFY_CHECK(pubkeylen == oldlen); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { |
||||
secp256k1_scalar_t factor; |
||||
secp256k1_scalar_t sec; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
DEBUG_CHECK(seckey != NULL); |
||||
DEBUG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
||||
secp256k1_scalar_set_b32(&sec, seckey, NULL); |
||||
ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow; |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &sec); |
||||
} |
||||
|
||||
secp256k1_scalar_clear(&sec); |
||||
secp256k1_scalar_clear(&factor); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { |
||||
secp256k1_ge_t p; |
||||
secp256k1_scalar_t factor; |
||||
int ret = 0; |
||||
int overflow = 0; |
||||
DEBUG_CHECK(secp256k1_ecmult_consts != NULL); |
||||
DEBUG_CHECK(pubkey != NULL); |
||||
DEBUG_CHECK(tweak != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow); |
||||
if (!overflow) { |
||||
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); |
||||
if (ret) { |
||||
ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor); |
||||
} |
||||
if (ret) { |
||||
int oldlen = pubkeylen; |
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); |
||||
VERIFY_CHECK(pubkeylen == oldlen); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { |
||||
secp256k1_scalar_t key; |
||||
int ret = 0; |
||||
DEBUG_CHECK(seckey != NULL); |
||||
DEBUG_CHECK(privkey != NULL); |
||||
DEBUG_CHECK(privkeylen != NULL); |
||||
|
||||
secp256k1_scalar_set_b32(&key, seckey, NULL); |
||||
ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed); |
||||
secp256k1_scalar_clear(&key); |
||||
return ret; |
||||
} |
||||
|
||||
int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { |
||||
secp256k1_scalar_t key; |
||||
int ret = 0; |
||||
DEBUG_CHECK(seckey != NULL); |
||||
DEBUG_CHECK(privkey != NULL); |
||||
|
||||
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); |
||||
if (ret) { |
||||
secp256k1_scalar_get_b32(seckey, &key); |
||||
} |
||||
secp256k1_scalar_clear(&key); |
||||
return ret; |
||||
} |
Loading…
Reference in new issue