Gav Wood
11 years ago
35 changed files with 4047 additions and 26 deletions
@ -0,0 +1,13 @@ |
|||||
|
cmake_policy(SET CMP0015 NEW) |
||||
|
|
||||
|
set(CMAKE_ASM_COMPILER "yasm") |
||||
|
|
||||
|
#aux_source_directory(. SRC_LIST) |
||||
|
add_library(secp256k1 secp256k1.c field_5x52_asm.asm) |
||||
|
|
||||
|
#set(CMAKE_C_FLAGS "-DUSE_FIELD_5X52 -DUSE_FIELD_5X52_ASM -DUSE_NUM_OPENSSL -DUSE_FIELD_INV_BUILTIN") |
||||
|
#target_link_libraries(secp256k1 crypto) |
||||
|
set(CMAKE_C_FLAGS "-std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") |
||||
|
target_link_libraries(secp256k1 gmp) |
||||
|
|
||||
|
|
@ -0,0 +1,19 @@ |
|||||
|
Copyright (c) 2013 Pieter Wuille |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
of this software and associated documentation files (the "Software"), to deal |
||||
|
in the Software without restriction, including without limitation the rights |
||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
copies of the Software, and to permit persons to whom the Software is |
||||
|
furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in |
||||
|
all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
THE SOFTWARE. |
@ -0,0 +1,28 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_ECDSA_ |
||||
|
#define _SECP256K1_ECDSA_ |
||||
|
|
||||
|
#include "num.h" |
||||
|
|
||||
|
typedef struct { |
||||
|
secp256k1_num_t r, s; |
||||
|
} secp256k1_ecdsa_sig_t; |
||||
|
|
||||
|
void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r); |
||||
|
void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r); |
||||
|
|
||||
|
int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); |
||||
|
void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); |
||||
|
int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); |
||||
|
int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); |
||||
|
int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); |
||||
|
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid); |
||||
|
int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); |
||||
|
void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); |
||||
|
int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); |
||||
|
int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); |
||||
|
|
||||
|
#endif |
@ -0,0 +1,19 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 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); |
||||
|
|
||||
|
/** Multiply with the generator: R = a*G */ |
||||
|
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a); |
||||
|
/** Double multiply: R = na*A + ng*G */ |
||||
|
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng); |
||||
|
|
||||
|
#endif |
@ -0,0 +1,99 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_ |
||||
|
#define _SECP256K1_FIELD_ |
||||
|
|
||||
|
/** Field element module.
|
||||
|
* |
||||
|
* Field elements can be represented in several ways, but code accessing |
||||
|
* it (and implementations) need to take certain properaties into account: |
||||
|
* - Each field element can be normalized or not. |
||||
|
* - Each field element has a magnitude, which represents how far away |
||||
|
* its representation is away from normalization. Normalized elements |
||||
|
* always have a magnitude of 1, but a magnitude of 1 doesn't imply |
||||
|
* normality. |
||||
|
*/ |
||||
|
|
||||
|
#if defined(USE_FIELD_GMP) |
||||
|
#include "field_gmp.h" |
||||
|
#elif defined(USE_FIELD_10X26) |
||||
|
#include "field_10x26.h" |
||||
|
#elif defined(USE_FIELD_5X52) |
||||
|
#include "field_5x52.h" |
||||
|
#else |
||||
|
#error "Please select field implementation" |
||||
|
#endif |
||||
|
|
||||
|
typedef struct { |
||||
|
secp256k1_num_t p; |
||||
|
} secp256k1_fe_consts_t; |
||||
|
|
||||
|
static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL; |
||||
|
|
||||
|
/** Initialize field element precomputation data. */ |
||||
|
void static secp256k1_fe_start(void); |
||||
|
|
||||
|
/** Unload field element precomputation data. */ |
||||
|
void static secp256k1_fe_stop(void); |
||||
|
|
||||
|
/** Normalize a field element. */ |
||||
|
void static secp256k1_fe_normalize(secp256k1_fe_t *r); |
||||
|
|
||||
|
/** Set a field element equal to a small integer. Resulting field element is normalized. */ |
||||
|
void static secp256k1_fe_set_int(secp256k1_fe_t *r, int a); |
||||
|
|
||||
|
/** Verify whether a field element is zero. Requires the input to be normalized. */ |
||||
|
int static secp256k1_fe_is_zero(const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Check the "oddness" of a field element. Requires the input to be normalized. */ |
||||
|
int static secp256k1_fe_is_odd(const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Compare two field elements. Requires both inputs to be normalized */ |
||||
|
int static secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b); |
||||
|
|
||||
|
/** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */ |
||||
|
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a); |
||||
|
|
||||
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
||||
|
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
|
||||
|
* as an argument. The magnitude of the output is one higher. */ |
||||
|
void static secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m); |
||||
|
|
||||
|
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
|
||||
|
* small integer. */ |
||||
|
void static secp256k1_fe_mul_int(secp256k1_fe_t *r, int a); |
||||
|
|
||||
|
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ |
||||
|
void static secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
|
||||
|
* The output magnitude is 1 (but not guaranteed to be normalized). */ |
||||
|
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b); |
||||
|
|
||||
|
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
|
||||
|
* The output magnitude is 1 (but not guaranteed to be normalized). */ |
||||
|
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Sets a field element to be the (modular) square root of another. Requires the inputs' magnitude to
|
||||
|
* be at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ |
||||
|
void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
|
||||
|
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ |
||||
|
void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ |
||||
|
void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a); |
||||
|
|
||||
|
|
||||
|
/** Convert a field element to a hexadecimal string. */ |
||||
|
void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a); |
||||
|
|
||||
|
/** Convert a hexadecimal string to a field element. */ |
||||
|
void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen); |
||||
|
|
||||
|
#endif |
@ -0,0 +1,19 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_ |
||||
|
#define _SECP256K1_FIELD_REPR_ |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
typedef struct { |
||||
|
// X = sum(i=0..9, elem[i]*2^26) mod n
|
||||
|
uint32_t n[10]; |
||||
|
#ifdef VERIFY |
||||
|
int magnitude; |
||||
|
int normalized; |
||||
|
#endif |
||||
|
} secp256k1_fe_t; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,19 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_ |
||||
|
#define _SECP256K1_FIELD_REPR_ |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
typedef struct { |
||||
|
// X = sum(i=0..4, elem[i]*2^52) mod n
|
||||
|
uint64_t n[5]; |
||||
|
#ifdef VERIFY |
||||
|
int magnitude; |
||||
|
int normalized; |
||||
|
#endif |
||||
|
} secp256k1_fe_t; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,463 @@ |
|||||
|
;; Added by Diederik Huys, March 2013 |
||||
|
;; |
||||
|
;; Provided public procedures: |
||||
|
;; secp256k1_fe_mul_inner |
||||
|
;; secp256k1_fe_sqr_inner |
||||
|
;; |
||||
|
;; Needed tools: YASM (http://yasm.tortall.net) |
||||
|
;; |
||||
|
;; |
||||
|
|
||||
|
BITS 64 |
||||
|
|
||||
|
;; Procedure ExSetMult |
||||
|
;; Register Layout: |
||||
|
;; INPUT: rdi = a->n |
||||
|
;; rsi = b->n |
||||
|
;; rdx = r->a |
||||
|
;; |
||||
|
;; INTERNAL: rdx:rax = multiplication accumulator |
||||
|
;; r9:r8 = c |
||||
|
;; r10-r13 = t0-t3 |
||||
|
;; r14 = b.n[0] / t4 |
||||
|
;; r15 = b.n[1] / t5 |
||||
|
;; rbx = b.n[2] / t6 |
||||
|
;; rcx = b.n[3] / t7 |
||||
|
;; rbp = Constant 0FFFFFFFFFFFFFh / t8 |
||||
|
;; rsi = b.n / b.n[4] / t9 |
||||
|
|
||||
|
GLOBAL secp256k1_fe_mul_inner |
||||
|
ALIGN 32 |
||||
|
secp256k1_fe_mul_inner: |
||||
|
push rbp |
||||
|
push rbx |
||||
|
push r12 |
||||
|
push r13 |
||||
|
push r14 |
||||
|
push r15 |
||||
|
push rdx |
||||
|
mov r14,[rsi+8*0] ; preload b.n[0]. This will be the case until |
||||
|
; b.n[0] is no longer needed, then we reassign |
||||
|
; r14 to t4 |
||||
|
;; c=a.n[0] * b.n[0] |
||||
|
mov rax,[rdi+0*8] ; load a.n[0] |
||||
|
mov rbp,0FFFFFFFFFFFFFh |
||||
|
mul r14 ; rdx:rax=a.n[0]*b.n[0] |
||||
|
mov r15,[rsi+1*8] |
||||
|
mov r10,rbp ; load modulus into target register for t0 |
||||
|
mov r8,rax |
||||
|
and r10,rax ; only need lower qword of c |
||||
|
shrd r8,rdx,52 |
||||
|
xor r9,r9 ; c < 2^64, so we ditch the HO part |
||||
|
|
||||
|
;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0] |
||||
|
mov rax,[rdi+0*8] |
||||
|
mul r15 |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+1*8] |
||||
|
mul r14 |
||||
|
mov r11,rbp |
||||
|
mov rbx,[rsi+2*8] |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r11,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[0 1 2] * b.n[2 1 0] |
||||
|
mov rax,[rdi+0*8] |
||||
|
mul rbx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+1*8] |
||||
|
mul r15 |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+2*8] |
||||
|
mul r14 |
||||
|
mov r12,rbp |
||||
|
mov rcx,[rsi+3*8] |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r12,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[0 1 2 3] * b.n[3 2 1 0] |
||||
|
mov rax,[rdi+0*8] |
||||
|
mul rcx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+1*8] |
||||
|
mul rbx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+2*8] |
||||
|
mul r15 |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+3*8] |
||||
|
mul r14 |
||||
|
mov r13,rbp |
||||
|
mov rsi,[rsi+4*8] ; load b.n[4] and destroy pointer |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r13,r8 |
||||
|
|
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
|
||||
|
;; c+=a.n[0 1 2 3 4] * b.n[4 3 2 1 0] |
||||
|
mov rax,[rdi+0*8] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+1*8] |
||||
|
mul rcx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+2*8] |
||||
|
mul rbx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+3*8] |
||||
|
mul r15 |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+4*8] |
||||
|
mul r14 |
||||
|
mov r14,rbp ; load modulus into t4 and destroy a.n[0] |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r14,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[1 2 3 4] * b.n[4 3 2 1] |
||||
|
mov rax,[rdi+1*8] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+2*8] |
||||
|
mul rcx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+3*8] |
||||
|
mul rbx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+4*8] |
||||
|
mul r15 |
||||
|
mov r15,rbp |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
and r15,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[2 3 4] * b.n[4 3 2] |
||||
|
mov rax,[rdi+2*8] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+3*8] |
||||
|
mul rcx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+4*8] |
||||
|
mul rbx |
||||
|
mov rbx,rbp |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
and rbx,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[3 4] * b.n[4 3] |
||||
|
mov rax,[rdi+3*8] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,[rdi+4*8] |
||||
|
mul rcx |
||||
|
mov rcx,rbp |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and rcx,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[4] * b.n[4] |
||||
|
mov rax,[rdi+4*8] |
||||
|
mul rsi |
||||
|
;; mov rbp,rbp ; modulus already there! |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and rbp,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rsi,r8 ; load c into t9 and destroy b.n[4] |
||||
|
|
||||
|
;; ******************************************************* |
||||
|
common_exit_norm: |
||||
|
mov rdi,01000003D10h ; load constant |
||||
|
|
||||
|
mov rax,r15 ; get t5 |
||||
|
mul rdi |
||||
|
add rax,r10 ; +t0 |
||||
|
adc rdx,0 |
||||
|
mov r10,0FFFFFFFFFFFFFh ; modulus. Sadly, we ran out of registers! |
||||
|
mov r8,rax ; +c |
||||
|
and r10,rax |
||||
|
shrd r8,rdx,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rax,rbx ; get t6 |
||||
|
mul rdi |
||||
|
add rax,r11 ; +t1 |
||||
|
adc rdx,0 |
||||
|
mov r11,0FFFFFFFFFFFFFh ; modulus |
||||
|
add r8,rax ; +c |
||||
|
adc r9,rdx |
||||
|
and r11,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rax,rcx ; get t7 |
||||
|
mul rdi |
||||
|
add rax,r12 ; +t2 |
||||
|
adc rdx,0 |
||||
|
pop rbx ; retrieve pointer to this.n |
||||
|
mov r12,0FFFFFFFFFFFFFh ; modulus |
||||
|
add r8,rax ; +c |
||||
|
adc r9,rdx |
||||
|
and r12,r8 |
||||
|
mov [rbx+2*8],r12 ; mov into this.n[2] |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rax,rbp ; get t8 |
||||
|
mul rdi |
||||
|
add rax,r13 ; +t3 |
||||
|
adc rdx,0 |
||||
|
mov r13,0FFFFFFFFFFFFFh ; modulus |
||||
|
add r8,rax ; +c |
||||
|
adc r9,rdx |
||||
|
and r13,r8 |
||||
|
mov [rbx+3*8],r13 ; -> this.n[3] |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rax,rsi ; get t9 |
||||
|
mul rdi |
||||
|
add rax,r14 ; +t4 |
||||
|
adc rdx,0 |
||||
|
mov r14,0FFFFFFFFFFFFh ; !!! |
||||
|
add r8,rax ; +c |
||||
|
adc r9,rdx |
||||
|
and r14,r8 |
||||
|
mov [rbx+4*8],r14 ; -> this.n[4] |
||||
|
shrd r8,r9,48 ; !!! |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rax,01000003D1h |
||||
|
mul r8 |
||||
|
add rax,r10 |
||||
|
adc rdx,0 |
||||
|
mov r10,0FFFFFFFFFFFFFh ; modulus |
||||
|
mov r8,rax |
||||
|
and rax,r10 |
||||
|
shrd r8,rdx,52 |
||||
|
mov [rbx+0*8],rax ; -> this.n[0] |
||||
|
add r8,r11 |
||||
|
mov [rbx+1*8],r8 ; -> this.n[1] |
||||
|
|
||||
|
pop r15 |
||||
|
pop r14 |
||||
|
pop r13 |
||||
|
pop r12 |
||||
|
pop rbx |
||||
|
pop rbp |
||||
|
ret |
||||
|
|
||||
|
|
||||
|
;; PROC ExSetSquare |
||||
|
;; Register Layout: |
||||
|
;; INPUT: rdi = a.n |
||||
|
;; rsi = this.a |
||||
|
;; INTERNAL: rdx:rax = multiplication accumulator |
||||
|
;; r9:r8 = c |
||||
|
;; r10-r13 = t0-t3 |
||||
|
;; r14 = a.n[0] / t4 |
||||
|
;; r15 = a.n[1] / t5 |
||||
|
;; rbx = a.n[2] / t6 |
||||
|
;; rcx = a.n[3] / t7 |
||||
|
;; rbp = 0FFFFFFFFFFFFFh / t8 |
||||
|
;; rsi = a.n[4] / t9 |
||||
|
GLOBAL secp256k1_fe_sqr_inner |
||||
|
ALIGN 32 |
||||
|
secp256k1_fe_sqr_inner: |
||||
|
push rbp |
||||
|
push rbx |
||||
|
push r12 |
||||
|
push r13 |
||||
|
push r14 |
||||
|
push r15 |
||||
|
push rsi |
||||
|
mov rbp,0FFFFFFFFFFFFFh |
||||
|
|
||||
|
;; c=a.n[0] * a.n[0] |
||||
|
mov r14,[rdi+0*8] ; r14=a.n[0] |
||||
|
mov r10,rbp ; modulus |
||||
|
mov rax,r14 |
||||
|
mul rax |
||||
|
mov r15,[rdi+1*8] ; a.n[1] |
||||
|
add r14,r14 ; r14=2*a.n[0] |
||||
|
mov r8,rax |
||||
|
and r10,rax ; only need lower qword |
||||
|
shrd r8,rdx,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[0] * a.n[1] |
||||
|
mov rax,r14 ; r14=2*a.n[0] |
||||
|
mul r15 |
||||
|
mov rbx,[rdi+2*8] ; rbx=a.n[2] |
||||
|
mov r11,rbp ; modulus |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r11,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1] |
||||
|
mov rax,r14 |
||||
|
mul rbx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,r15 |
||||
|
mov r12,rbp ; modulus |
||||
|
mul rax |
||||
|
mov rcx,[rdi+3*8] ; rcx=a.n[3] |
||||
|
add r15,r15 ; r15=a.n[1]*2 |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r12,r8 ; only need lower dword |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2] |
||||
|
mov rax,r14 |
||||
|
mul rcx |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,r15 ; rax=2*a.n[1] |
||||
|
mov r13,rbp ; modulus |
||||
|
mul rbx |
||||
|
mov rsi,[rdi+4*8] ; rsi=a.n[4] |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r13,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[0]*a.n[4]+2*a.n[1]*a.n[3]+a.n[2]*a.n[2] |
||||
|
mov rax,r14 ; last time we need 2*a.n[0] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,r15 |
||||
|
mul rcx |
||||
|
mov r14,rbp ; modulus |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,rbx |
||||
|
mul rax |
||||
|
add rbx,rbx ; rcx=2*a.n[2] |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r14,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[1]*a.n[4]+2*a.n[2]*a.n[3] |
||||
|
mov rax,r15 ; last time we need 2*a.n[1] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,rbx |
||||
|
mul rcx |
||||
|
mov r15,rbp ; modulus |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and r15,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[2]*a.n[4]+a.n[3]*a.n[3] |
||||
|
mov rax,rbx ; last time we need 2*a.n[2] |
||||
|
mul rsi |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
|
||||
|
mov rax,rcx ; a.n[3] |
||||
|
mul rax |
||||
|
mov rbx,rbp ; modulus |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and rbx,r8 ; only need lower dword |
||||
|
lea rax,[2*rcx] |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=2*a.n[3]*a.n[4] |
||||
|
mul rsi |
||||
|
mov rcx,rbp ; modulus |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and rcx,r8 ; only need lower dword |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
;; c+=a.n[4]*a.n[4] |
||||
|
mov rax,rsi |
||||
|
mul rax |
||||
|
;; mov rbp,rbp ; modulus is already there! |
||||
|
add r8,rax |
||||
|
adc r9,rdx |
||||
|
and rbp,r8 |
||||
|
shrd r8,r9,52 |
||||
|
xor r9,r9 |
||||
|
|
||||
|
mov rsi,r8 |
||||
|
|
||||
|
;; ******************************************************* |
||||
|
jmp common_exit_norm |
||||
|
end |
||||
|
|
||||
|
|
@ -0,0 +1,16 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_ |
||||
|
#define _SECP256K1_FIELD_REPR_ |
||||
|
|
||||
|
#include <gmp.h> |
||||
|
|
||||
|
#define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) |
||||
|
|
||||
|
typedef struct { |
||||
|
mp_limb_t n[FIELD_LIMBS+1]; |
||||
|
} secp256k1_fe_t; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,110 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 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; |
||||
|
|
||||
|
/** 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; |
||||
|
|
||||
|
/** Global constants related to the group */ |
||||
|
typedef struct { |
||||
|
secp256k1_num_t order; // the order of the curve (= order of its generator)
|
||||
|
secp256k1_num_t half_order; // half the order of the curve (= order of its generator)
|
||||
|
secp256k1_ge_t g; // the generator point
|
||||
|
|
||||
|
// constants related to secp256k1's efficiently computable endomorphism
|
||||
|
secp256k1_fe_t beta; |
||||
|
secp256k1_num_t lambda, a1b2, b1, a2; |
||||
|
} secp256k1_ge_consts_t; |
||||
|
|
||||
|
static const secp256k1_ge_consts_t *secp256k1_ge_consts = NULL; |
||||
|
|
||||
|
/** Initialize the group module. */ |
||||
|
void static secp256k1_ge_start(void); |
||||
|
|
||||
|
/** De-initialize the group module. */ |
||||
|
void static secp256k1_ge_stop(void); |
||||
|
|
||||
|
/** Set a group element equal to the point at infinity */ |
||||
|
void static secp256k1_ge_set_infinity(secp256k1_ge_t *r); |
||||
|
|
||||
|
/** Set a group element equal to the point with given X and Y coordinates */ |
||||
|
void static secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); |
||||
|
|
||||
|
/** Set a group element (jacobian) equal to the point with given X coordinate, and given oddness for Y.
|
||||
|
The result is not guaranteed to be valid. */ |
||||
|
void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd); |
||||
|
|
||||
|
/** Check whether a group element is the point at infinity. */ |
||||
|
int static secp256k1_ge_is_infinity(const secp256k1_ge_t *a); |
||||
|
|
||||
|
/** Check whether a group element is valid (i.e., on the curve). */ |
||||
|
int static secp256k1_ge_is_valid(const secp256k1_ge_t *a); |
||||
|
|
||||
|
void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a); |
||||
|
|
||||
|
/** Get a hex representation of a point. *rlen will be overwritten with the real length. */ |
||||
|
void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a); |
||||
|
|
||||
|
/** Set a group element equal to another which is given in jacobian coordinates */ |
||||
|
void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); |
||||
|
|
||||
|
|
||||
|
/** Set a group element (jacobian) equal to the point at infinity. */ |
||||
|
void static secp256k1_gej_set_infinity(secp256k1_gej_t *r); |
||||
|
|
||||
|
/** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ |
||||
|
void static 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. */ |
||||
|
void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); |
||||
|
|
||||
|
/** Get the X coordinate of a group element (jacobian). */ |
||||
|
void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a); |
||||
|
|
||||
|
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ |
||||
|
void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
|
|
||||
|
/** Check whether a group element is the point at infinity. */ |
||||
|
int static secp256k1_gej_is_infinity(const secp256k1_gej_t *a); |
||||
|
|
||||
|
/** Set r equal to the double of a. */ |
||||
|
void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
|
|
||||
|
/** Set r equal to the sum of a and b. */ |
||||
|
void static secp256k1_gej_add(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 jacobian coordinates). This is more efficient
|
||||
|
than secp256k1_gej_add. */ |
||||
|
void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); |
||||
|
|
||||
|
/** Get a hex representation of a point. *rlen will be overwritten with the real length. */ |
||||
|
void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); |
||||
|
|
||||
|
#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. */ |
||||
|
void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); |
||||
|
|
||||
|
/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is
|
||||
|
not more than 256 bits). */ |
||||
|
void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); |
||||
|
#endif |
||||
|
|
||||
|
#endif |
@ -0,0 +1,307 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_ECDSA_IMPL_H_ |
||||
|
#define _SECP256K1_ECDSA_IMPL_H_ |
||||
|
|
||||
|
#include "../num.h" |
||||
|
#include "../field.h" |
||||
|
#include "../group.h" |
||||
|
#include "../ecmult.h" |
||||
|
#include "../ecdsa.h" |
||||
|
|
||||
|
void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r) { |
||||
|
secp256k1_num_init(&r->r); |
||||
|
secp256k1_num_init(&r->s); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r) { |
||||
|
secp256k1_num_free(&r->r); |
||||
|
secp256k1_num_free(&r->s); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { |
||||
|
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { |
||||
|
secp256k1_fe_t x; |
||||
|
secp256k1_fe_set_b32(&x, pub+1); |
||||
|
secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); |
||||
|
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { |
||||
|
secp256k1_fe_t x, y; |
||||
|
secp256k1_fe_set_b32(&x, pub+1); |
||||
|
secp256k1_fe_set_b32(&y, pub+33); |
||||
|
secp256k1_ge_set_xy(elem, &x, &y); |
||||
|
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) |
||||
|
return 0; |
||||
|
} else { |
||||
|
return 0; |
||||
|
} |
||||
|
return secp256k1_ge_is_valid(elem); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { |
||||
|
if (sig[0] != 0x30) return 0; |
||||
|
int lenr = sig[3]; |
||||
|
if (5+lenr >= size) return 0; |
||||
|
int lens = sig[lenr+5]; |
||||
|
if (sig[1] != lenr+lens+4) return 0; |
||||
|
if (lenr+lens+6 > size) return 0; |
||||
|
if (sig[2] != 0x02) return 0; |
||||
|
if (lenr == 0) return 0; |
||||
|
if (sig[lenr+4] != 0x02) return 0; |
||||
|
if (lens == 0) return 0; |
||||
|
secp256k1_num_set_bin(&r->r, sig+4, lenr); |
||||
|
secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { |
||||
|
int lenR = (secp256k1_num_bits(&a->r) + 7)/8; |
||||
|
if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) |
||||
|
lenR++; |
||||
|
int lenS = (secp256k1_num_bits(&a->s) + 7)/8; |
||||
|
if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) |
||||
|
lenS++; |
||||
|
if (*size < 6+lenS+lenR) |
||||
|
return 0; |
||||
|
*size = 6 + lenS + lenR; |
||||
|
sig[0] = 0x30; |
||||
|
sig[1] = 4 + lenS + lenR; |
||||
|
sig[2] = 0x02; |
||||
|
sig[3] = lenR; |
||||
|
secp256k1_num_get_bin(sig+4, lenR, &a->r); |
||||
|
sig[4+lenR] = 0x02; |
||||
|
sig[5+lenR] = lenS; |
||||
|
secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { |
||||
|
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; |
||||
|
|
||||
|
if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) |
||||
|
return 0; |
||||
|
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) |
||||
|
return 0; |
||||
|
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) |
||||
|
return 0; |
||||
|
|
||||
|
int ret = 0; |
||||
|
secp256k1_num_t sn, u1, u2; |
||||
|
secp256k1_num_init(&sn); |
||||
|
secp256k1_num_init(&u1); |
||||
|
secp256k1_num_init(&u2); |
||||
|
secp256k1_num_mod_inverse(&sn, &sig->s, &c->order); |
||||
|
secp256k1_num_mod_mul(&u1, &sn, message, &c->order); |
||||
|
secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order); |
||||
|
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); |
||||
|
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); |
||||
|
if (!secp256k1_gej_is_infinity(&pr)) { |
||||
|
secp256k1_fe_t xr; secp256k1_gej_get_x(&xr, &pr); |
||||
|
secp256k1_fe_normalize(&xr); |
||||
|
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); |
||||
|
secp256k1_num_set_bin(r2, xrb, 32); |
||||
|
secp256k1_num_mod(r2, &c->order); |
||||
|
ret = 1; |
||||
|
} |
||||
|
secp256k1_num_free(&sn); |
||||
|
secp256k1_num_free(&u1); |
||||
|
secp256k1_num_free(&u2); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) { |
||||
|
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; |
||||
|
|
||||
|
if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) |
||||
|
return 0; |
||||
|
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) |
||||
|
return 0; |
||||
|
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) |
||||
|
return 0; |
||||
|
|
||||
|
secp256k1_num_t rx; |
||||
|
secp256k1_num_init(&rx); |
||||
|
secp256k1_num_copy(&rx, &sig->r); |
||||
|
if (recid & 2) { |
||||
|
secp256k1_num_add(&rx, &rx, &c->order); |
||||
|
if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0) |
||||
|
return 0; |
||||
|
} |
||||
|
unsigned char brx[32]; |
||||
|
secp256k1_num_get_bin(brx, 32, &rx); |
||||
|
secp256k1_num_free(&rx); |
||||
|
secp256k1_fe_t fx; |
||||
|
secp256k1_fe_set_b32(&fx, brx); |
||||
|
secp256k1_ge_t x; |
||||
|
secp256k1_ge_set_xo(&x, &fx, recid & 1); |
||||
|
if (!secp256k1_ge_is_valid(&x)) |
||||
|
return 0; |
||||
|
secp256k1_gej_t xj; |
||||
|
secp256k1_gej_set_ge(&xj, &x); |
||||
|
secp256k1_num_t rn, u1, u2; |
||||
|
secp256k1_num_init(&rn); |
||||
|
secp256k1_num_init(&u1); |
||||
|
secp256k1_num_init(&u2); |
||||
|
secp256k1_num_mod_inverse(&rn, &sig->r, &c->order); |
||||
|
secp256k1_num_mod_mul(&u1, &rn, message, &c->order); |
||||
|
secp256k1_num_sub(&u1, &c->order, &u1); |
||||
|
secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order); |
||||
|
secp256k1_gej_t qj; |
||||
|
secp256k1_ecmult(&qj, &xj, &u2, &u1); |
||||
|
secp256k1_ge_set_gej(pubkey, &qj); |
||||
|
secp256k1_num_free(&rn); |
||||
|
secp256k1_num_free(&u1); |
||||
|
secp256k1_num_free(&u2); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { |
||||
|
secp256k1_num_t r2; |
||||
|
secp256k1_num_init(&r2); |
||||
|
int ret = 0; |
||||
|
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; |
||||
|
secp256k1_num_free(&r2); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid) { |
||||
|
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; |
||||
|
|
||||
|
secp256k1_gej_t rp; |
||||
|
secp256k1_ecmult_gen(&rp, nonce); |
||||
|
secp256k1_ge_t r; |
||||
|
secp256k1_ge_set_gej(&r, &rp); |
||||
|
unsigned char b[32]; |
||||
|
secp256k1_fe_normalize(&r.x); |
||||
|
secp256k1_fe_normalize(&r.y); |
||||
|
secp256k1_fe_get_b32(b, &r.x); |
||||
|
secp256k1_num_set_bin(&sig->r, b, 32); |
||||
|
if (recid) |
||||
|
*recid = (secp256k1_num_cmp(&sig->r, &c->order) >= 0 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); |
||||
|
secp256k1_num_mod(&sig->r, &c->order); |
||||
|
secp256k1_num_t n; |
||||
|
secp256k1_num_init(&n); |
||||
|
secp256k1_num_mod_mul(&n, &sig->r, seckey, &c->order); |
||||
|
secp256k1_num_add(&n, &n, message); |
||||
|
secp256k1_num_mod(&n, &c->order); |
||||
|
secp256k1_num_mod_inverse(&sig->s, nonce, &c->order); |
||||
|
secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order); |
||||
|
secp256k1_num_free(&n); |
||||
|
if (secp256k1_num_is_zero(&sig->s)) |
||||
|
return 0; |
||||
|
if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) { |
||||
|
secp256k1_num_sub(&sig->s, &c->order, &sig->s); |
||||
|
if (recid) |
||||
|
*recid ^= 1; |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { |
||||
|
secp256k1_num_copy(&sig->r, r); |
||||
|
secp256k1_num_copy(&sig->s, s); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { |
||||
|
secp256k1_fe_normalize(&elem->x); |
||||
|
secp256k1_fe_normalize(&elem->y); |
||||
|
secp256k1_fe_get_b32(&pub[1], &elem->x); |
||||
|
if (compressed) { |
||||
|
*size = 33; |
||||
|
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); |
||||
|
} else { |
||||
|
*size = 65; |
||||
|
pub[0] = 0x04; |
||||
|
secp256k1_fe_get_b32(&pub[33], &elem->y); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { |
||||
|
const unsigned char *end = privkey + privkeylen; |
||||
|
// sequence header
|
||||
|
if (end < privkey+1 || *privkey != 0x30) |
||||
|
return 0; |
||||
|
privkey++; |
||||
|
// sequence length constructor
|
||||
|
int lenb = 0; |
||||
|
if (end < privkey+1 || !(*privkey & 0x80)) |
||||
|
return 0; |
||||
|
lenb = *privkey & ~0x80; privkey++; |
||||
|
if (lenb < 1 || lenb > 2) |
||||
|
return 0; |
||||
|
if (end < privkey+lenb) |
||||
|
return 0; |
||||
|
// sequence length
|
||||
|
int len = 0; |
||||
|
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); |
||||
|
privkey += lenb; |
||||
|
if (end < privkey+len) |
||||
|
return 0; |
||||
|
// sequence element 0: version number (=1)
|
||||
|
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) |
||||
|
return 0; |
||||
|
privkey += 3; |
||||
|
// sequence element 1: octet string, up to 32 bytes
|
||||
|
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) |
||||
|
return 0; |
||||
|
secp256k1_num_set_bin(key, privkey+2, privkey[1]); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { |
||||
|
secp256k1_gej_t rp; |
||||
|
secp256k1_ecmult_gen(&rp, key); |
||||
|
secp256k1_ge_t r; |
||||
|
secp256k1_ge_set_gej(&r, &rp); |
||||
|
if (compressed) { |
||||
|
static const unsigned char begin[] = { |
||||
|
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 |
||||
|
}; |
||||
|
static const unsigned char middle[] = { |
||||
|
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, |
||||
|
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, |
||||
|
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, |
||||
|
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, |
||||
|
0x17,0x98,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,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 |
||||
|
}; |
||||
|
unsigned char *ptr = privkey; |
||||
|
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); |
||||
|
secp256k1_num_get_bin(ptr, 32, key); ptr += 32; |
||||
|
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); |
||||
|
int pubkeylen = 0; |
||||
|
secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; |
||||
|
*privkeylen = ptr - privkey; |
||||
|
} else { |
||||
|
static const unsigned char begin[] = { |
||||
|
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 |
||||
|
}; |
||||
|
static const unsigned char middle[] = { |
||||
|
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, |
||||
|
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, |
||||
|
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, |
||||
|
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, |
||||
|
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, |
||||
|
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, |
||||
|
0xD4,0xB8,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,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 |
||||
|
}; |
||||
|
unsigned char *ptr = privkey; |
||||
|
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); |
||||
|
secp256k1_num_get_bin(ptr, 32, key); ptr += 32; |
||||
|
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); |
||||
|
int pubkeylen = 0; |
||||
|
secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; |
||||
|
*privkeylen = ptr - privkey; |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,259 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 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 "../num.h" |
||||
|
#include "../group.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. WINDOW_G == 14 results in 640 KiB.
|
||||
|
#define WINDOW_G 14 |
||||
|
|
||||
|
/** 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. |
||||
|
*/ |
||||
|
void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { |
||||
|
pre[0] = *a; |
||||
|
secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]); |
||||
|
for (int i=1; i<(1 << (w-2)); i++) |
||||
|
secp256k1_gej_add(&pre[i], &d, &pre[i-1]); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_ge_t *a, int w) { |
||||
|
pre[0] = *a; |
||||
|
secp256k1_gej_t x; secp256k1_gej_set_ge(&x, a); |
||||
|
secp256k1_gej_t d; secp256k1_gej_double(&d, &x); |
||||
|
for (int i=1; i<(1 << (w-2)); i++) { |
||||
|
secp256k1_gej_add_ge(&x, &d, &pre[i-1]); |
||||
|
secp256k1_ge_set_gej(&pre[i], &x); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** 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(r,pre,n,w,neg) do { \ |
||||
|
assert(((n) & 1) == 1); \ |
||||
|
assert((n) >= -((1 << ((w)-1)) - 1)); \ |
||||
|
assert((n) <= ((1 << ((w)-1)) - 1)); \ |
||||
|
if ((n) > 0) \ |
||||
|
*(r) = (pre)[((n)-1)/2]; \ |
||||
|
else \ |
||||
|
(neg)((r), &(pre)[(-(n)-1)/2]); \ |
||||
|
} while(0) |
||||
|
|
||||
|
#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg) |
||||
|
#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg) |
||||
|
|
||||
|
typedef struct { |
||||
|
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
|
||||
|
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
|
||||
|
secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
|
||||
|
secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
|
||||
|
} secp256k1_ecmult_consts_t; |
||||
|
|
||||
|
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; |
||||
|
|
||||
|
static void secp256k1_ecmult_start(void) { |
||||
|
if (secp256k1_ecmult_consts != NULL) |
||||
|
return; |
||||
|
|
||||
|
secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); |
||||
|
secp256k1_ecmult_consts = ret; |
||||
|
|
||||
|
// get the generator
|
||||
|
const secp256k1_ge_t *g = &secp256k1_ge_consts->g; |
||||
|
|
||||
|
// calculate 2^128*generator
|
||||
|
secp256k1_gej_t g_128j; secp256k1_gej_set_ge(&g_128j, g); |
||||
|
for (int i=0; i<128; i++) |
||||
|
secp256k1_gej_double(&g_128j, &g_128j); |
||||
|
secp256k1_ge_t g_128; secp256k1_ge_set_gej(&g_128, &g_128j); |
||||
|
|
||||
|
// precompute the tables with odd multiples
|
||||
|
secp256k1_ecmult_table_precomp_ge(ret->pre_g, g, WINDOW_G); |
||||
|
secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128, WINDOW_G); |
||||
|
|
||||
|
// compute prec and fin
|
||||
|
secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g); |
||||
|
secp256k1_ge_t ad = *g; |
||||
|
secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn); |
||||
|
for (int j=0; j<64; j++) { |
||||
|
secp256k1_ge_set_gej(&ret->prec[j][0], &gg); |
||||
|
secp256k1_gej_add(&fn, &fn, &gg); |
||||
|
for (int i=1; i<16; i++) { |
||||
|
secp256k1_gej_add_ge(&gg, &gg, &ad); |
||||
|
secp256k1_ge_set_gej(&ret->prec[j][i], &gg); |
||||
|
} |
||||
|
ad = ret->prec[j][15]; |
||||
|
} |
||||
|
secp256k1_ge_set_gej(&ret->fin, &fn); |
||||
|
secp256k1_ge_neg(&ret->fin, &ret->fin); |
||||
|
} |
||||
|
|
||||
|
static void secp256k1_ecmult_stop(void) { |
||||
|
if (secp256k1_ecmult_consts == NULL) |
||||
|
return; |
||||
|
|
||||
|
secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; |
||||
|
free(c); |
||||
|
secp256k1_ecmult_consts = NULL; |
||||
|
} |
||||
|
|
||||
|
/** 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 index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where |
||||
|
* bits is the number of bits necessary to represent the absolute value of the input. |
||||
|
*/ |
||||
|
static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { |
||||
|
int ret = 0; |
||||
|
int zeroes = 0; |
||||
|
secp256k1_num_t x; |
||||
|
secp256k1_num_init(&x); |
||||
|
secp256k1_num_copy(&x, a); |
||||
|
int sign = 1; |
||||
|
if (secp256k1_num_is_neg(&x)) { |
||||
|
sign = -1; |
||||
|
secp256k1_num_negate(&x); |
||||
|
} |
||||
|
while (!secp256k1_num_is_zero(&x)) { |
||||
|
while (!secp256k1_num_is_odd(&x)) { |
||||
|
zeroes++; |
||||
|
secp256k1_num_shift(&x, 1); |
||||
|
} |
||||
|
int word = secp256k1_num_shift(&x, w); |
||||
|
while (zeroes) { |
||||
|
wnaf[ret++] = 0; |
||||
|
zeroes--; |
||||
|
} |
||||
|
if (word & (1 << (w-1))) { |
||||
|
secp256k1_num_inc(&x); |
||||
|
wnaf[ret++] = sign * (word - (1 << w)); |
||||
|
} else { |
||||
|
wnaf[ret++] = sign * word; |
||||
|
} |
||||
|
zeroes = w-1; |
||||
|
} |
||||
|
secp256k1_num_free(&x); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { |
||||
|
secp256k1_num_t n; |
||||
|
secp256k1_num_init(&n); |
||||
|
secp256k1_num_copy(&n, gn); |
||||
|
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; |
||||
|
secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]); |
||||
|
for (int j=1; j<64; j++) |
||||
|
secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]); |
||||
|
secp256k1_num_free(&n); |
||||
|
secp256k1_gej_add_ge(r, r, &c->fin); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { |
||||
|
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; |
||||
|
|
||||
|
#ifdef USE_ENDOMORPHISM |
||||
|
secp256k1_num_t na_1, na_lam; |
||||
|
secp256k1_num_init(&na_1); |
||||
|
secp256k1_num_init(&na_lam); |
||||
|
// 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_gej_split_exp(&na_1, &na_lam, na); |
||||
|
|
||||
|
// build wnaf representation for na_1 and na_lam.
|
||||
|
int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); |
||||
|
int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); |
||||
|
int bits = bits_na_1; |
||||
|
if (bits_na_lam > bits) bits = bits_na_lam; |
||||
|
|
||||
|
// calculate a_lam = a*lambda
|
||||
|
secp256k1_gej_t a_lam; secp256k1_gej_mul_lambda(&a_lam, a); |
||||
|
|
||||
|
// calculate odd multiples of a_lam
|
||||
|
secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
|
secp256k1_ecmult_table_precomp_gej(pre_a_lam, &a_lam, WINDOW_A); |
||||
|
#else |
||||
|
// build wnaf representation for na.
|
||||
|
int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); |
||||
|
int bits = bits_na; |
||||
|
#endif |
||||
|
|
||||
|
// calculate odd multiples of a
|
||||
|
secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; |
||||
|
secp256k1_ecmult_table_precomp_gej(pre_a, a, WINDOW_A); |
||||
|
|
||||
|
// Splitted G factors.
|
||||
|
secp256k1_num_t ng_1, ng_128; |
||||
|
secp256k1_num_init(&ng_1); |
||||
|
secp256k1_num_init(&ng_128); |
||||
|
|
||||
|
// 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_num_split(&ng_1, &ng_128, ng, 128); |
||||
|
|
||||
|
// Build wnaf representation for ng_1 and ng_128
|
||||
|
int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); |
||||
|
int wnaf_ng_128[129]; int 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; |
||||
|
|
||||
|
secp256k1_gej_set_infinity(r); |
||||
|
secp256k1_gej_t tmpj; |
||||
|
secp256k1_ge_t tmpa; |
||||
|
|
||||
|
for (int i=bits-1; i>=0; i--) { |
||||
|
secp256k1_gej_double(r, r); |
||||
|
int n; |
||||
|
#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(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(r, r, &tmpj); |
||||
|
} |
||||
|
#else |
||||
|
if (i < bits_na && (n = wnaf_na[i])) { |
||||
|
ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); |
||||
|
secp256k1_gej_add(r, r, &tmpj); |
||||
|
} |
||||
|
#endif |
||||
|
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { |
||||
|
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); |
||||
|
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
|
} |
||||
|
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { |
||||
|
ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); |
||||
|
secp256k1_gej_add_ge(r, r, &tmpa); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef USE_ENDOMORPHISM |
||||
|
secp256k1_num_free(&na_1); |
||||
|
secp256k1_num_free(&na_lam); |
||||
|
#endif |
||||
|
secp256k1_num_free(&ng_1); |
||||
|
secp256k1_num_free(&ng_128); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,173 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_IMPL_H_ |
||||
|
|
||||
|
#if defined(USE_FIELD_GMP) |
||||
|
#include "field_gmp.h" |
||||
|
#elif defined(USE_FIELD_10X26) |
||||
|
#include "field_10x26.h" |
||||
|
#elif defined(USE_FIELD_5X52) |
||||
|
#include "field_5x52.h" |
||||
|
#else |
||||
|
#error "Please select field implementation" |
||||
|
#endif |
||||
|
|
||||
|
void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) { |
||||
|
if (*rlen < 65) { |
||||
|
*rlen = 65; |
||||
|
return; |
||||
|
} |
||||
|
*rlen = 65; |
||||
|
unsigned char tmp[32]; |
||||
|
secp256k1_fe_t b = *a; |
||||
|
secp256k1_fe_normalize(&b); |
||||
|
secp256k1_fe_get_b32(tmp, &b); |
||||
|
for (int i=0; i<32; i++) { |
||||
|
static const char *c = "0123456789ABCDEF"; |
||||
|
r[2*i] = c[(tmp[i] >> 4) & 0xF]; |
||||
|
r[2*i+1] = c[(tmp[i]) & 0xF]; |
||||
|
} |
||||
|
r[64] = 0x00; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) { |
||||
|
unsigned char tmp[32] = {}; |
||||
|
static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, |
||||
|
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}; |
||||
|
for (int i=0; i<32; i++) { |
||||
|
if (alen > i*2) |
||||
|
tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]]; |
||||
|
} |
||||
|
secp256k1_fe_set_b32(r, tmp); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
// calculate a^p, with p={15,780,1022,1023}
|
||||
|
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); |
||||
|
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); |
||||
|
secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3); |
||||
|
secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6); |
||||
|
secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3); |
||||
|
secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15); |
||||
|
secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30); |
||||
|
secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60); |
||||
|
secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120); |
||||
|
secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15); |
||||
|
secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255); |
||||
|
secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240); |
||||
|
secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30); |
||||
|
secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510); |
||||
|
secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2); |
||||
|
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a); |
||||
|
secp256k1_fe_t x = a15; |
||||
|
for (int i=0; i<21; i++) { |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1023); |
||||
|
} |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1022); |
||||
|
for (int i=0; i<2; i++) { |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1023); |
||||
|
} |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(r, &x, &a780); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
// calculate a^p, with p={45,63,1019,1023}
|
||||
|
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); |
||||
|
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); |
||||
|
secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2); |
||||
|
secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a); |
||||
|
secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5); |
||||
|
secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a); |
||||
|
secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10); |
||||
|
secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21); |
||||
|
secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3); |
||||
|
secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21); |
||||
|
secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63); |
||||
|
secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126); |
||||
|
secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252); |
||||
|
secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504); |
||||
|
secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11); |
||||
|
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4); |
||||
|
secp256k1_fe_t x = a63; |
||||
|
for (int i=0; i<21; i++) { |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1023); |
||||
|
} |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1019); |
||||
|
for (int i=0; i<2; i++) { |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(&x, &x, &a1023); |
||||
|
} |
||||
|
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); |
||||
|
secp256k1_fe_mul(r, &x, &a45); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
#if defined(USE_FIELD_INV_BUILTIN) |
||||
|
secp256k1_fe_inv(r, a); |
||||
|
#elif defined(USE_FIELD_INV_NUM) |
||||
|
unsigned char b[32]; |
||||
|
secp256k1_fe_t c = *a; |
||||
|
secp256k1_fe_normalize(&c); |
||||
|
secp256k1_fe_get_b32(b, &c); |
||||
|
secp256k1_num_t n; |
||||
|
secp256k1_num_init(&n); |
||||
|
secp256k1_num_set_bin(&n, b, 32); |
||||
|
secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p); |
||||
|
secp256k1_num_get_bin(b, 32, &n); |
||||
|
secp256k1_num_free(&n); |
||||
|
secp256k1_fe_set_b32(r, b); |
||||
|
#else |
||||
|
#error "Please select field inverse implementation" |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_start(void) { |
||||
|
static const unsigned char secp256k1_fe_consts_p[] = { |
||||
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, |
||||
|
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F |
||||
|
}; |
||||
|
if (secp256k1_fe_consts == NULL) { |
||||
|
secp256k1_fe_inner_start(); |
||||
|
secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t)); |
||||
|
secp256k1_num_init(&ret->p); |
||||
|
secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p)); |
||||
|
secp256k1_fe_consts = ret; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_stop(void) { |
||||
|
if (secp256k1_fe_consts != NULL) { |
||||
|
secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts; |
||||
|
secp256k1_num_free(&c->p); |
||||
|
free((void*)c); |
||||
|
secp256k1_fe_consts = NULL; |
||||
|
secp256k1_fe_inner_stop(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,487 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <assert.h> |
||||
|
#include <string.h> |
||||
|
#include "../num.h" |
||||
|
#include "../field.h" |
||||
|
|
||||
|
void static secp256k1_fe_inner_start(void) {} |
||||
|
void static secp256k1_fe_inner_stop(void) {} |
||||
|
|
||||
|
void static secp256k1_fe_normalize(secp256k1_fe_t *r) { |
||||
|
// fog("normalize in: ", r);
|
||||
|
uint32_t c; |
||||
|
c = r->n[0]; |
||||
|
uint32_t t0 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[1]; |
||||
|
uint32_t t1 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[2]; |
||||
|
uint32_t t2 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[3]; |
||||
|
uint32_t t3 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[4]; |
||||
|
uint32_t t4 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[5]; |
||||
|
uint32_t t5 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[6]; |
||||
|
uint32_t t6 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[7]; |
||||
|
uint32_t t7 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[8]; |
||||
|
uint32_t t8 = c & 0x3FFFFFFUL; |
||||
|
c = (c >> 26) + r->n[9]; |
||||
|
uint32_t t9 = c & 0x03FFFFFUL; |
||||
|
c >>= 22; |
||||
|
/* r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; |
||||
|
fog(" tm1: ", r); |
||||
|
fprintf(stderr, "out c= %08lx\n", (unsigned long)c);*/ |
||||
|
|
||||
|
// The following code will not modify the t's if c is initially 0.
|
||||
|
uint32_t d = c * 0x3D1UL + t0; |
||||
|
t0 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t1 + c*0x40; |
||||
|
t1 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t2; |
||||
|
t2 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t3; |
||||
|
t3 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t4; |
||||
|
t4 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t5; |
||||
|
t5 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t6; |
||||
|
t6 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t7; |
||||
|
t7 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t8; |
||||
|
t8 = d & 0x3FFFFFFULL; |
||||
|
d = (d >> 26) + t9; |
||||
|
t9 = d & 0x03FFFFFULL; |
||||
|
assert((d >> 22) == 0); |
||||
|
/* r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
|
||||
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; |
||||
|
fog(" tm2: ", r); */ |
||||
|
|
||||
|
// Subtract p if result >= p
|
||||
|
uint64_t low = ((uint64_t)t1 << 26) | t0; |
||||
|
uint64_t mask = -(int64_t)((t9 < 0x03FFFFFUL) | (t8 < 0x3FFFFFFUL) | (t7 < 0x3FFFFFFUL) | (t6 < 0x3FFFFFFUL) | (t5 < 0x3FFFFFFUL) | (t4 < 0x3FFFFFFUL) | (t3 < 0x3FFFFFFUL) | (t2 < 0x3FFFFFFUL) | (low < 0xFFFFEFFFFFC2FULL)); |
||||
|
t9 &= mask; |
||||
|
t8 &= mask; |
||||
|
t7 &= mask; |
||||
|
t6 &= mask; |
||||
|
t5 &= mask; |
||||
|
t4 &= mask; |
||||
|
t3 &= mask; |
||||
|
t2 &= mask; |
||||
|
low -= (~mask & 0xFFFFEFFFFFC2FULL); |
||||
|
|
||||
|
// push internal variables back
|
||||
|
r->n[0] = low & 0x3FFFFFFUL; r->n[1] = (low >> 26) & 0x3FFFFFFUL; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; |
||||
|
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; |
||||
|
/* fog(" out: ", r);*/ |
||||
|
|
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { |
||||
|
r->n[0] = a; |
||||
|
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
// TODO: not constant time!
|
||||
|
int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0 && a->n[5] == 0 && a->n[6] == 0 && a->n[7] == 0 && a->n[8] == 0 && a->n[9] == 0); |
||||
|
} |
||||
|
|
||||
|
int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
return a->n[0] & 1; |
||||
|
} |
||||
|
|
||||
|
// TODO: not constant time!
|
||||
|
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
assert(b->normalized); |
||||
|
#endif |
||||
|
return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4] && |
||||
|
a->n[5] == b->n[5] && a->n[6] == b->n[6] && a->n[7] == b->n[7] && a->n[8] == b->n[8] && a->n[9] == b->n[9]); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { |
||||
|
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; |
||||
|
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; |
||||
|
for (int i=0; i<32; i++) { |
||||
|
for (int j=0; j<4; j++) { |
||||
|
int limb = (8*i+2*j)/26; |
||||
|
int shift = (8*i+2*j)%26; |
||||
|
r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; |
||||
|
} |
||||
|
} |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
||||
|
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
for (int i=0; i<32; i++) { |
||||
|
int c = 0; |
||||
|
for (int j=0; j<4; j++) { |
||||
|
int limb = (8*i+2*j)/26; |
||||
|
int shift = (8*i+2*j)%26; |
||||
|
c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); |
||||
|
} |
||||
|
r[31-i] = c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= m); |
||||
|
r->magnitude = m + 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] = 0x3FFFC2FUL * (m + 1) - a->n[0]; |
||||
|
r->n[1] = 0x3FFFFBFUL * (m + 1) - a->n[1]; |
||||
|
r->n[2] = 0x3FFFFFFUL * (m + 1) - a->n[2]; |
||||
|
r->n[3] = 0x3FFFFFFUL * (m + 1) - a->n[3]; |
||||
|
r->n[4] = 0x3FFFFFFUL * (m + 1) - a->n[4]; |
||||
|
r->n[5] = 0x3FFFFFFUL * (m + 1) - a->n[5]; |
||||
|
r->n[6] = 0x3FFFFFFUL * (m + 1) - a->n[6]; |
||||
|
r->n[7] = 0x3FFFFFFUL * (m + 1) - a->n[7]; |
||||
|
r->n[8] = 0x3FFFFFFUL * (m + 1) - a->n[8]; |
||||
|
r->n[9] = 0x03FFFFFUL * (m + 1) - a->n[9]; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude *= a; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] *= a; |
||||
|
r->n[1] *= a; |
||||
|
r->n[2] *= a; |
||||
|
r->n[3] *= a; |
||||
|
r->n[4] *= a; |
||||
|
r->n[5] *= a; |
||||
|
r->n[6] *= a; |
||||
|
r->n[7] *= a; |
||||
|
r->n[8] *= a; |
||||
|
r->n[9] *= a; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude += a->magnitude; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] += a->n[0]; |
||||
|
r->n[1] += a->n[1]; |
||||
|
r->n[2] += a->n[2]; |
||||
|
r->n[3] += a->n[3]; |
||||
|
r->n[4] += a->n[4]; |
||||
|
r->n[5] += a->n[5]; |
||||
|
r->n[6] += a->n[6]; |
||||
|
r->n[7] += a->n[7]; |
||||
|
r->n[8] += a->n[8]; |
||||
|
r->n[9] += a->n[9]; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) { |
||||
|
uint64_t c = (uint64_t)a[0] * b[0]; |
||||
|
uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[1] + |
||||
|
(uint64_t)a[1] * b[0]; |
||||
|
uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[2] + |
||||
|
(uint64_t)a[1] * b[1] + |
||||
|
(uint64_t)a[2] * b[0]; |
||||
|
uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[3] + |
||||
|
(uint64_t)a[1] * b[2] + |
||||
|
(uint64_t)a[2] * b[1] + |
||||
|
(uint64_t)a[3] * b[0]; |
||||
|
uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[4] + |
||||
|
(uint64_t)a[1] * b[3] + |
||||
|
(uint64_t)a[2] * b[2] + |
||||
|
(uint64_t)a[3] * b[1] + |
||||
|
(uint64_t)a[4] * b[0]; |
||||
|
uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[5] + |
||||
|
(uint64_t)a[1] * b[4] + |
||||
|
(uint64_t)a[2] * b[3] + |
||||
|
(uint64_t)a[3] * b[2] + |
||||
|
(uint64_t)a[4] * b[1] + |
||||
|
(uint64_t)a[5] * b[0]; |
||||
|
uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[6] + |
||||
|
(uint64_t)a[1] * b[5] + |
||||
|
(uint64_t)a[2] * b[4] + |
||||
|
(uint64_t)a[3] * b[3] + |
||||
|
(uint64_t)a[4] * b[2] + |
||||
|
(uint64_t)a[5] * b[1] + |
||||
|
(uint64_t)a[6] * b[0]; |
||||
|
uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[7] + |
||||
|
(uint64_t)a[1] * b[6] + |
||||
|
(uint64_t)a[2] * b[5] + |
||||
|
(uint64_t)a[3] * b[4] + |
||||
|
(uint64_t)a[4] * b[3] + |
||||
|
(uint64_t)a[5] * b[2] + |
||||
|
(uint64_t)a[6] * b[1] + |
||||
|
(uint64_t)a[7] * b[0]; |
||||
|
uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[8] + |
||||
|
(uint64_t)a[1] * b[7] + |
||||
|
(uint64_t)a[2] * b[6] + |
||||
|
(uint64_t)a[3] * b[5] + |
||||
|
(uint64_t)a[4] * b[4] + |
||||
|
(uint64_t)a[5] * b[3] + |
||||
|
(uint64_t)a[6] * b[2] + |
||||
|
(uint64_t)a[7] * b[1] + |
||||
|
(uint64_t)a[8] * b[0]; |
||||
|
uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[0] * b[9] + |
||||
|
(uint64_t)a[1] * b[8] + |
||||
|
(uint64_t)a[2] * b[7] + |
||||
|
(uint64_t)a[3] * b[6] + |
||||
|
(uint64_t)a[4] * b[5] + |
||||
|
(uint64_t)a[5] * b[4] + |
||||
|
(uint64_t)a[6] * b[3] + |
||||
|
(uint64_t)a[7] * b[2] + |
||||
|
(uint64_t)a[8] * b[1] + |
||||
|
(uint64_t)a[9] * b[0]; |
||||
|
uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[1] * b[9] + |
||||
|
(uint64_t)a[2] * b[8] + |
||||
|
(uint64_t)a[3] * b[7] + |
||||
|
(uint64_t)a[4] * b[6] + |
||||
|
(uint64_t)a[5] * b[5] + |
||||
|
(uint64_t)a[6] * b[4] + |
||||
|
(uint64_t)a[7] * b[3] + |
||||
|
(uint64_t)a[8] * b[2] + |
||||
|
(uint64_t)a[9] * b[1]; |
||||
|
uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[2] * b[9] + |
||||
|
(uint64_t)a[3] * b[8] + |
||||
|
(uint64_t)a[4] * b[7] + |
||||
|
(uint64_t)a[5] * b[6] + |
||||
|
(uint64_t)a[6] * b[5] + |
||||
|
(uint64_t)a[7] * b[4] + |
||||
|
(uint64_t)a[8] * b[3] + |
||||
|
(uint64_t)a[9] * b[2]; |
||||
|
uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[3] * b[9] + |
||||
|
(uint64_t)a[4] * b[8] + |
||||
|
(uint64_t)a[5] * b[7] + |
||||
|
(uint64_t)a[6] * b[6] + |
||||
|
(uint64_t)a[7] * b[5] + |
||||
|
(uint64_t)a[8] * b[4] + |
||||
|
(uint64_t)a[9] * b[3]; |
||||
|
uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[4] * b[9] + |
||||
|
(uint64_t)a[5] * b[8] + |
||||
|
(uint64_t)a[6] * b[7] + |
||||
|
(uint64_t)a[7] * b[6] + |
||||
|
(uint64_t)a[8] * b[5] + |
||||
|
(uint64_t)a[9] * b[4]; |
||||
|
uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[5] * b[9] + |
||||
|
(uint64_t)a[6] * b[8] + |
||||
|
(uint64_t)a[7] * b[7] + |
||||
|
(uint64_t)a[8] * b[6] + |
||||
|
(uint64_t)a[9] * b[5]; |
||||
|
uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[6] * b[9] + |
||||
|
(uint64_t)a[7] * b[8] + |
||||
|
(uint64_t)a[8] * b[7] + |
||||
|
(uint64_t)a[9] * b[6]; |
||||
|
uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[7] * b[9] + |
||||
|
(uint64_t)a[8] * b[8] + |
||||
|
(uint64_t)a[9] * b[7]; |
||||
|
uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[8] * b[9] + |
||||
|
(uint64_t)a[9] * b[8]; |
||||
|
uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[9] * b[9]; |
||||
|
uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
uint32_t t19 = c; |
||||
|
|
||||
|
c = t0 + (uint64_t)t10 * 0x3D10UL; |
||||
|
t0 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL; |
||||
|
t1 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL; |
||||
|
t2 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL; |
||||
|
r[3] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL; |
||||
|
r[4] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL; |
||||
|
r[5] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL; |
||||
|
r[6] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL; |
||||
|
r[7] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL; |
||||
|
r[8] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL; |
||||
|
r[9] = c & 0x03FFFFFUL; c = c >> 22; |
||||
|
uint64_t d = t0 + c * 0x3D1UL; |
||||
|
r[0] = d & 0x3FFFFFFUL; d = d >> 26; |
||||
|
d = d + t1 + c*0x40; |
||||
|
r[1] = d & 0x3FFFFFFUL; d = d >> 26; |
||||
|
r[2] = t2 + d; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) { |
||||
|
uint64_t c = (uint64_t)a[0] * a[0]; |
||||
|
uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[1]; |
||||
|
uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[2] + |
||||
|
(uint64_t)a[1] * a[1]; |
||||
|
uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[3] + |
||||
|
(uint64_t)(a[1]*2) * a[2]; |
||||
|
uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[4] + |
||||
|
(uint64_t)(a[1]*2) * a[3] + |
||||
|
(uint64_t)a[2] * a[2]; |
||||
|
uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[5] + |
||||
|
(uint64_t)(a[1]*2) * a[4] + |
||||
|
(uint64_t)(a[2]*2) * a[3]; |
||||
|
uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[6] + |
||||
|
(uint64_t)(a[1]*2) * a[5] + |
||||
|
(uint64_t)(a[2]*2) * a[4] + |
||||
|
(uint64_t)a[3] * a[3]; |
||||
|
uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[7] + |
||||
|
(uint64_t)(a[1]*2) * a[6] + |
||||
|
(uint64_t)(a[2]*2) * a[5] + |
||||
|
(uint64_t)(a[3]*2) * a[4]; |
||||
|
uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[8] + |
||||
|
(uint64_t)(a[1]*2) * a[7] + |
||||
|
(uint64_t)(a[2]*2) * a[6] + |
||||
|
(uint64_t)(a[3]*2) * a[5] + |
||||
|
(uint64_t)a[4] * a[4]; |
||||
|
uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[0]*2) * a[9] + |
||||
|
(uint64_t)(a[1]*2) * a[8] + |
||||
|
(uint64_t)(a[2]*2) * a[7] + |
||||
|
(uint64_t)(a[3]*2) * a[6] + |
||||
|
(uint64_t)(a[4]*2) * a[5]; |
||||
|
uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[1]*2) * a[9] + |
||||
|
(uint64_t)(a[2]*2) * a[8] + |
||||
|
(uint64_t)(a[3]*2) * a[7] + |
||||
|
(uint64_t)(a[4]*2) * a[6] + |
||||
|
(uint64_t)a[5] * a[5]; |
||||
|
uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[2]*2) * a[9] + |
||||
|
(uint64_t)(a[3]*2) * a[8] + |
||||
|
(uint64_t)(a[4]*2) * a[7] + |
||||
|
(uint64_t)(a[5]*2) * a[6]; |
||||
|
uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[3]*2) * a[9] + |
||||
|
(uint64_t)(a[4]*2) * a[8] + |
||||
|
(uint64_t)(a[5]*2) * a[7] + |
||||
|
(uint64_t)a[6] * a[6]; |
||||
|
uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[4]*2) * a[9] + |
||||
|
(uint64_t)(a[5]*2) * a[8] + |
||||
|
(uint64_t)(a[6]*2) * a[7]; |
||||
|
uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[5]*2) * a[9] + |
||||
|
(uint64_t)(a[6]*2) * a[8] + |
||||
|
(uint64_t)a[7] * a[7]; |
||||
|
uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[6]*2) * a[9] + |
||||
|
(uint64_t)(a[7]*2) * a[8]; |
||||
|
uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[7]*2) * a[9] + |
||||
|
(uint64_t)a[8] * a[8]; |
||||
|
uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)(a[8]*2) * a[9]; |
||||
|
uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + (uint64_t)a[9] * a[9]; |
||||
|
uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
uint32_t t19 = c; |
||||
|
|
||||
|
c = t0 + (uint64_t)t10 * 0x3D10UL; |
||||
|
t0 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL; |
||||
|
t1 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL; |
||||
|
t2 = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL; |
||||
|
r[3] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL; |
||||
|
r[4] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL; |
||||
|
r[5] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL; |
||||
|
r[6] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL; |
||||
|
r[7] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL; |
||||
|
r[8] = c & 0x3FFFFFFUL; c = c >> 26; |
||||
|
c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL; |
||||
|
r[9] = c & 0x03FFFFFUL; c = c >> 22; |
||||
|
uint64_t d = t0 + c * 0x3D1UL; |
||||
|
r[0] = d & 0x3FFFFFFUL; d = d >> 26; |
||||
|
d = d + t1 + c*0x40; |
||||
|
r[1] = d & 0x3FFFFFFUL; d = d >> 26; |
||||
|
r[2] = t2 + d; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= 8); |
||||
|
assert(b->magnitude <= 8); |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
secp256k1_fe_mul_inner(a->n, b->n, r->n); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= 8); |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
secp256k1_fe_sqr_inner(a->n, r->n); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,196 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
#include <string.h> |
||||
|
#include "../num.h" |
||||
|
#include "../field.h" |
||||
|
|
||||
|
#if defined(USE_FIELD_5X52_ASM) |
||||
|
#include "field_5x52_asm.h" |
||||
|
#elif defined(USE_FIELD_5X52_INT128) |
||||
|
#include "field_5x52_int128.h" |
||||
|
#else |
||||
|
#error "Please select field_5x52 implementation" |
||||
|
#endif |
||||
|
|
||||
|
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
|
||||
|
* represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, |
||||
|
* each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element |
||||
|
* is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations |
||||
|
* accept any input with magnitude at most M, and have different rules for propagating magnitude to their |
||||
|
* output. |
||||
|
*/ |
||||
|
|
||||
|
void static secp256k1_fe_inner_start(void) {} |
||||
|
void static secp256k1_fe_inner_stop(void) {} |
||||
|
|
||||
|
void static secp256k1_fe_normalize(secp256k1_fe_t *r) { |
||||
|
uint64_t c; |
||||
|
c = r->n[0]; |
||||
|
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + r->n[1]; |
||||
|
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + r->n[2]; |
||||
|
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + r->n[3]; |
||||
|
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + r->n[4]; |
||||
|
uint64_t t4 = c & 0x0FFFFFFFFFFFFULL; |
||||
|
c >>= 48; |
||||
|
|
||||
|
// The following code will not modify the t's if c is initially 0.
|
||||
|
c = c * 0x1000003D1ULL + t0; |
||||
|
t0 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + t1; |
||||
|
t1 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + t2; |
||||
|
t2 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + t3; |
||||
|
t3 = c & 0xFFFFFFFFFFFFFULL; |
||||
|
c = (c >> 52) + t4; |
||||
|
t4 = c & 0x0FFFFFFFFFFFFULL; |
||||
|
assert((c >> 48) == 0); |
||||
|
|
||||
|
// Subtract p if result >= p
|
||||
|
uint64_t mask = -(int64_t)((t4 < 0xFFFFFFFFFFFFULL) | (t3 < 0xFFFFFFFFFFFFFULL) | (t2 < 0xFFFFFFFFFFFFFULL) | (t1 < 0xFFFFFFFFFFFFFULL) | (t0 < 0xFFFFEFFFFFC2FULL)); |
||||
|
t4 &= mask; |
||||
|
t3 &= mask; |
||||
|
t2 &= mask; |
||||
|
t1 &= mask; |
||||
|
t0 -= (~mask & 0xFFFFEFFFFFC2FULL); |
||||
|
|
||||
|
// push internal variables back
|
||||
|
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; |
||||
|
|
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { |
||||
|
r->n[0] = a; |
||||
|
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
// TODO: not constant time!
|
||||
|
int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0); |
||||
|
} |
||||
|
|
||||
|
int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
return a->n[0] & 1; |
||||
|
} |
||||
|
|
||||
|
// TODO: not constant time!
|
||||
|
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
assert(b->normalized); |
||||
|
#endif |
||||
|
return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4]); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { |
||||
|
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; |
||||
|
for (int i=0; i<32; i++) { |
||||
|
for (int j=0; j<2; j++) { |
||||
|
int limb = (8*i+4*j)/52; |
||||
|
int shift = (8*i+4*j)%52; |
||||
|
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; |
||||
|
} |
||||
|
} |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 1; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
||||
|
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->normalized); |
||||
|
#endif |
||||
|
for (int i=0; i<32; i++) { |
||||
|
int c = 0; |
||||
|
for (int j=0; j<2; j++) { |
||||
|
int limb = (8*i+4*j)/52; |
||||
|
int shift = (8*i+4*j)%52; |
||||
|
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); |
||||
|
} |
||||
|
r[31-i] = c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= m); |
||||
|
r->magnitude = m + 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] = 0xFFFFEFFFFFC2FULL * (m + 1) - a->n[0]; |
||||
|
r->n[1] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[1]; |
||||
|
r->n[2] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[2]; |
||||
|
r->n[3] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[3]; |
||||
|
r->n[4] = 0x0FFFFFFFFFFFFULL * (m + 1) - a->n[4]; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude *= a; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] *= a; |
||||
|
r->n[1] *= a; |
||||
|
r->n[2] *= a; |
||||
|
r->n[3] *= a; |
||||
|
r->n[4] *= a; |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
r->magnitude += a->magnitude; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
r->n[0] += a->n[0]; |
||||
|
r->n[1] += a->n[1]; |
||||
|
r->n[2] += a->n[2]; |
||||
|
r->n[3] += a->n[3]; |
||||
|
r->n[4] += a->n[4]; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= 8); |
||||
|
assert(b->magnitude <= 8); |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
secp256k1_fe_mul_inner(a->n, b->n, r->n); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
#ifdef VERIFY |
||||
|
assert(a->magnitude <= 8); |
||||
|
r->magnitude = 1; |
||||
|
r->normalized = 0; |
||||
|
#endif |
||||
|
secp256k1_fe_sqr_inner(a->n, r->n); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,11 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ |
||||
|
|
||||
|
void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r); |
||||
|
void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r); |
||||
|
|
||||
|
#endif |
@ -0,0 +1,105 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
void static inline secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r) { |
||||
|
__int128 c = (__int128)a[0] * b[0]; |
||||
|
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
|
||||
|
c = c + (__int128)a[0] * b[1] + |
||||
|
(__int128)a[1] * b[0]; |
||||
|
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
|
||||
|
c = c + (__int128)a[0] * b[2] + |
||||
|
(__int128)a[1] * b[1] + |
||||
|
(__int128)a[2] * b[0]; |
||||
|
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
|
||||
|
c = c + (__int128)a[0] * b[3] + |
||||
|
(__int128)a[1] * b[2] + |
||||
|
(__int128)a[2] * b[1] + |
||||
|
(__int128)a[3] * b[0]; |
||||
|
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
|
||||
|
c = c + (__int128)a[0] * b[4] + |
||||
|
(__int128)a[1] * b[3] + |
||||
|
(__int128)a[2] * b[2] + |
||||
|
(__int128)a[3] * b[1] + |
||||
|
(__int128)a[4] * b[0]; |
||||
|
uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
|
||||
|
c = c + (__int128)a[1] * b[4] + |
||||
|
(__int128)a[2] * b[3] + |
||||
|
(__int128)a[3] * b[2] + |
||||
|
(__int128)a[4] * b[1]; |
||||
|
uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
|
||||
|
c = c + (__int128)a[2] * b[4] + |
||||
|
(__int128)a[3] * b[3] + |
||||
|
(__int128)a[4] * b[2]; |
||||
|
uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
|
||||
|
c = c + (__int128)a[3] * b[4] + |
||||
|
(__int128)a[4] * b[3]; |
||||
|
uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
|
||||
|
c = c + (__int128)a[4] * b[4]; |
||||
|
uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
|
||||
|
uint64_t t9 = c; |
||||
|
|
||||
|
c = t0 + (__int128)t5 * 0x1000003D10ULL; |
||||
|
t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t1 + (__int128)t6 * 0x1000003D10ULL; |
||||
|
t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t2 + (__int128)t7 * 0x1000003D10ULL; |
||||
|
r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t3 + (__int128)t8 * 0x1000003D10ULL; |
||||
|
r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t4 + (__int128)t9 * 0x1000003D10ULL; |
||||
|
r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
|
c = t0 + (__int128)c * 0x1000003D1ULL; |
||||
|
r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
|
r[1] = t1 + c; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r) { |
||||
|
__int128 c = (__int128)a[0] * a[0]; |
||||
|
uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
|
||||
|
c = c + (__int128)(a[0]*2) * a[1]; |
||||
|
uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
|
||||
|
c = c + (__int128)(a[0]*2) * a[2] + |
||||
|
(__int128)a[1] * a[1]; |
||||
|
uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
|
||||
|
c = c + (__int128)(a[0]*2) * a[3] + |
||||
|
(__int128)(a[1]*2) * a[2]; |
||||
|
uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
|
||||
|
c = c + (__int128)(a[0]*2) * a[4] + |
||||
|
(__int128)(a[1]*2) * a[3] + |
||||
|
(__int128)a[2] * a[2]; |
||||
|
uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
|
||||
|
c = c + (__int128)(a[1]*2) * a[4] + |
||||
|
(__int128)(a[2]*2) * a[3]; |
||||
|
uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
|
||||
|
c = c + (__int128)(a[2]*2) * a[4] + |
||||
|
(__int128)a[3] * a[3]; |
||||
|
uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
|
||||
|
c = c + (__int128)(a[3]*2) * a[4]; |
||||
|
uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
|
||||
|
c = c + (__int128)a[4] * a[4]; |
||||
|
uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
|
||||
|
uint64_t t9 = c; |
||||
|
c = t0 + (__int128)t5 * 0x1000003D10ULL; |
||||
|
t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t1 + (__int128)t6 * 0x1000003D10ULL; |
||||
|
t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t2 + (__int128)t7 * 0x1000003D10ULL; |
||||
|
r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t3 + (__int128)t8 * 0x1000003D10ULL; |
||||
|
r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
|
||||
|
c = c + t4 + (__int128)t9 * 0x1000003D10ULL; |
||||
|
r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
|
||||
|
c = t0 + (__int128)c * 0x1000003D1ULL; |
||||
|
r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
|
||||
|
r[1] = t1 + c; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,155 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
#define _SECP256K1_FIELD_REPR_IMPL_H_ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <assert.h> |
||||
|
#include <string.h> |
||||
|
#include "../num.h" |
||||
|
#include "../field.h" |
||||
|
|
||||
|
static mp_limb_t secp256k1_field_p[FIELD_LIMBS]; |
||||
|
static mp_limb_t secp256k1_field_pc[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; |
||||
|
|
||||
|
void static secp256k1_fe_inner_start(void) { |
||||
|
for (int i=0; i<(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; i++) |
||||
|
secp256k1_field_pc[i] = 0; |
||||
|
secp256k1_field_pc[0] += 0x3D1UL; |
||||
|
secp256k1_field_pc[32/GMP_NUMB_BITS] += (1UL << (32 % GMP_NUMB_BITS)); |
||||
|
for (int i=0; i<FIELD_LIMBS; i++) { |
||||
|
secp256k1_field_p[i] = 0; |
||||
|
} |
||||
|
mpn_sub(secp256k1_field_p, secp256k1_field_p, FIELD_LIMBS, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_inner_stop(void) { |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_normalize(secp256k1_fe_t *r) { |
||||
|
if (r->n[FIELD_LIMBS] != 0) { |
||||
|
#if (GMP_NUMB_BITS >= 40) |
||||
|
mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]); |
||||
|
mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry); |
||||
|
#else |
||||
|
mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) + |
||||
|
mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS)); |
||||
|
mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry); |
||||
|
mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS)); |
||||
|
#endif |
||||
|
r->n[FIELD_LIMBS] = 0; |
||||
|
} |
||||
|
if (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) >= 0) |
||||
|
mpn_sub(r->n, r->n, FIELD_LIMBS, secp256k1_field_p, FIELD_LIMBS); |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { |
||||
|
r->n[0] = a; |
||||
|
for (int i=1; i<FIELD_LIMBS+1; i++) |
||||
|
r->n[i] = 0; |
||||
|
} |
||||
|
|
||||
|
int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { |
||||
|
int ret = 1; |
||||
|
for (int i=0; i<FIELD_LIMBS+1; i++) |
||||
|
ret &= (a->n[i] == 0); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { |
||||
|
return a->n[0] & 1; |
||||
|
} |
||||
|
|
||||
|
int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
int ret = 1; |
||||
|
for (int i=0; i<FIELD_LIMBS+1; i++) |
||||
|
ret &= (a->n[i] == b->n[i]); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { |
||||
|
for (int i=0; i<FIELD_LIMBS+1; i++) |
||||
|
r->n[i] = 0; |
||||
|
for (int i=0; i<256; i++) { |
||||
|
int limb = i/GMP_NUMB_BITS; |
||||
|
int shift = i%GMP_NUMB_BITS; |
||||
|
r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
||||
|
void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { |
||||
|
for (int i=0; i<32; i++) { |
||||
|
int c = 0; |
||||
|
for (int j=0; j<8; j++) { |
||||
|
int limb = (8*i+j)/GMP_NUMB_BITS; |
||||
|
int shift = (8*i+j)%GMP_NUMB_BITS; |
||||
|
c |= ((a->n[limb] >> shift) & 0x1) << j; |
||||
|
} |
||||
|
r[31-i] = c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { |
||||
|
*r = *a; |
||||
|
secp256k1_fe_normalize(r); |
||||
|
for (int i=0; i<FIELD_LIMBS; i++) |
||||
|
r->n[i] = ~(r->n[i]); |
||||
|
#if (GMP_NUMB_BITS >= 33) |
||||
|
mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL); |
||||
|
#else |
||||
|
mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL); |
||||
|
mpn_sub_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { |
||||
|
mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a); |
||||
|
} |
||||
|
|
||||
|
void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) { |
||||
|
// <A1 A2 A3 A4> <B1 B2 B3 B4>
|
||||
|
// B1 B2 B3 B4
|
||||
|
// + C * A1 A2 A3 A4
|
||||
|
// + A1 A2 A3 A4
|
||||
|
|
||||
|
#if (GMP_NUMB_BITS >= 33) |
||||
|
mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL); |
||||
|
#else |
||||
|
mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x3D1UL) + |
||||
|
mpn_addmul_1(tmp+(32/GMP_NUMB_BITS), tmp+FIELD_LIMBS, FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); |
||||
|
#endif |
||||
|
mp_limb_t q[1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; |
||||
|
q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] = mpn_mul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o); |
||||
|
#if (GMP_NUMB_BITS <= 32) |
||||
|
mp_limb_t o2 = tmp[2*FIELD_LIMBS-(32/GMP_NUMB_BITS)] << (32%GMP_NUMB_BITS); |
||||
|
q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] += mpn_addmul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o2); |
||||
|
#endif |
||||
|
r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
||||
|
secp256k1_fe_t ac = *a; |
||||
|
secp256k1_fe_t bc = *b; |
||||
|
secp256k1_fe_normalize(&ac); |
||||
|
secp256k1_fe_normalize(&bc); |
||||
|
mp_limb_t tmp[2*FIELD_LIMBS]; |
||||
|
mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS); |
||||
|
secp256k1_fe_reduce(r, tmp); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { |
||||
|
secp256k1_fe_t ac = *a; |
||||
|
secp256k1_fe_normalize(&ac); |
||||
|
mp_limb_t tmp[2*FIELD_LIMBS]; |
||||
|
mpn_sqr(tmp, ac.n, FIELD_LIMBS); |
||||
|
secp256k1_fe_reduce(r, tmp); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,403 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 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" |
||||
|
|
||||
|
void static secp256k1_ge_set_infinity(secp256k1_ge_t *r) { |
||||
|
r->infinity = 1; |
||||
|
} |
||||
|
|
||||
|
void static 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; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ge_is_infinity(const secp256k1_ge_t *a) { |
||||
|
return a->infinity; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) { |
||||
|
r->infinity = a->infinity; |
||||
|
r->x = a->x; |
||||
|
r->y = a->y; |
||||
|
secp256k1_fe_normalize(&r->y); |
||||
|
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) { |
||||
|
char cx[65]; int lx=65; |
||||
|
char cy[65]; int ly=65; |
||||
|
secp256k1_fe_get_hex(cx, &lx, &a->x); |
||||
|
secp256k1_fe_get_hex(cy, &ly, &a->y); |
||||
|
lx = strlen(cx); |
||||
|
ly = strlen(cy); |
||||
|
int len = lx + ly + 3 + 1; |
||||
|
if (*rlen < len) { |
||||
|
*rlen = len; |
||||
|
return; |
||||
|
} |
||||
|
*rlen = len; |
||||
|
r[0] = '('; |
||||
|
memcpy(r+1, cx, lx); |
||||
|
r[1+lx] = ','; |
||||
|
memcpy(r+2+lx, cy, ly); |
||||
|
r[2+lx+ly] = ')'; |
||||
|
r[3+lx+ly] = 0; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { |
||||
|
secp256k1_fe_inv_var(&a->z, &a->z); |
||||
|
secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); |
||||
|
secp256k1_fe_t z3; 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->infinity = a->infinity; |
||||
|
r->x = a->x; |
||||
|
r->y = a->y; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_set_infinity(secp256k1_gej_t *r) { |
||||
|
r->infinity = 1; |
||||
|
} |
||||
|
|
||||
|
void static 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); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) { |
||||
|
r->x = *x; |
||||
|
secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x); |
||||
|
secp256k1_fe_t x3; secp256k1_fe_mul(&x3, x, &x2); |
||||
|
r->infinity = 0; |
||||
|
secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); |
||||
|
secp256k1_fe_add(&c, &x3); |
||||
|
secp256k1_fe_sqrt(&r->y, &c); |
||||
|
secp256k1_fe_normalize(&r->y); |
||||
|
if (secp256k1_fe_is_odd(&r->y) != odd) |
||||
|
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
|
} |
||||
|
|
||||
|
void static 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); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a) { |
||||
|
secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2); |
||||
|
secp256k1_fe_mul(r, &a->x, &zi2); |
||||
|
} |
||||
|
|
||||
|
void static 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(&r->y); |
||||
|
secp256k1_fe_negate(&r->y, &r->y, 1); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_gej_is_infinity(const secp256k1_gej_t *a) { |
||||
|
return a->infinity; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_gej_is_valid(const secp256k1_gej_t *a) { |
||||
|
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_t y2; secp256k1_fe_sqr(&y2, &a->y); |
||||
|
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
|
secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); |
||||
|
secp256k1_fe_t z6; 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(&y2); |
||||
|
secp256k1_fe_normalize(&x3); |
||||
|
return secp256k1_fe_equal(&y2, &x3); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_ge_is_valid(const secp256k1_ge_t *a) { |
||||
|
if (a->infinity) |
||||
|
return 0; |
||||
|
// y^2 = x^3 + 7
|
||||
|
secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y); |
||||
|
secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); |
||||
|
secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); |
||||
|
secp256k1_fe_add(&x3, &c); |
||||
|
secp256k1_fe_normalize(&y2); |
||||
|
secp256k1_fe_normalize(&x3); |
||||
|
return secp256k1_fe_equal(&y2, &x3); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a) { |
||||
|
secp256k1_fe_t t5 = a->y; |
||||
|
secp256k1_fe_normalize(&t5); |
||||
|
if (a->infinity || secp256k1_fe_is_zero(&t5)) { |
||||
|
r->infinity = 1; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
secp256k1_fe_t t1,t2,t3,t4; |
||||
|
secp256k1_fe_mul(&r->z, &t5, &a->z); |
||||
|
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, &t5); |
||||
|
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, &a->x, &t3); // 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)
|
||||
|
r->infinity = 0; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { |
||||
|
if (a->infinity) { |
||||
|
*r = *b; |
||||
|
return; |
||||
|
} |
||||
|
if (b->infinity) { |
||||
|
*r = *a; |
||||
|
return; |
||||
|
} |
||||
|
r->infinity = 0; |
||||
|
secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &b->z); |
||||
|
secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z); |
||||
|
secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &a->x, &z22); |
||||
|
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
|
secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); |
||||
|
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
|
secp256k1_fe_normalize(&u1); |
||||
|
secp256k1_fe_normalize(&u2); |
||||
|
if (secp256k1_fe_equal(&u1, &u2)) { |
||||
|
secp256k1_fe_normalize(&s1); |
||||
|
secp256k1_fe_normalize(&s2); |
||||
|
if (secp256k1_fe_equal(&s1, &s2)) { |
||||
|
secp256k1_gej_double(r, a); |
||||
|
} else { |
||||
|
r->infinity = 1; |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
|
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
|
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); |
||||
|
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); |
||||
|
secp256k1_fe_t h3; 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_t t; 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); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { |
||||
|
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_t z12; secp256k1_fe_sqr(&z12, &a->z); |
||||
|
secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); |
||||
|
secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); |
||||
|
secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); |
||||
|
secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); |
||||
|
secp256k1_fe_normalize(&u1); |
||||
|
secp256k1_fe_normalize(&u2); |
||||
|
if (secp256k1_fe_equal(&u1, &u2)) { |
||||
|
secp256k1_fe_normalize(&s1); |
||||
|
secp256k1_fe_normalize(&s2); |
||||
|
if (secp256k1_fe_equal(&s1, &s2)) { |
||||
|
secp256k1_gej_double(r, a); |
||||
|
} else { |
||||
|
r->infinity = 1; |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); |
||||
|
secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); |
||||
|
secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); |
||||
|
secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); |
||||
|
secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2); |
||||
|
r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); |
||||
|
secp256k1_fe_t t; 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); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) { |
||||
|
secp256k1_gej_t c = *a; |
||||
|
secp256k1_ge_t t; secp256k1_ge_set_gej(&t, &c); |
||||
|
secp256k1_ge_get_hex(r, rlen, &t); |
||||
|
} |
||||
|
|
||||
|
#ifdef USE_ENDOMORPHISM |
||||
|
void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) { |
||||
|
const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta; |
||||
|
*r = *a; |
||||
|
secp256k1_fe_mul(&r->x, &r->x, beta); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { |
||||
|
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; |
||||
|
secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2; |
||||
|
|
||||
|
secp256k1_num_init(&bnc1); |
||||
|
secp256k1_num_init(&bnc2); |
||||
|
secp256k1_num_init(&bnt1); |
||||
|
secp256k1_num_init(&bnt2); |
||||
|
secp256k1_num_init(&bnn2); |
||||
|
|
||||
|
secp256k1_num_copy(&bnn2, &c->order); |
||||
|
secp256k1_num_shift(&bnn2, 1); |
||||
|
|
||||
|
secp256k1_num_mul(&bnc1, a, &c->a1b2); |
||||
|
secp256k1_num_add(&bnc1, &bnc1, &bnn2); |
||||
|
secp256k1_num_div(&bnc1, &bnc1, &c->order); |
||||
|
|
||||
|
secp256k1_num_mul(&bnc2, a, &c->b1); |
||||
|
secp256k1_num_add(&bnc2, &bnc2, &bnn2); |
||||
|
secp256k1_num_div(&bnc2, &bnc2, &c->order); |
||||
|
|
||||
|
secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2); |
||||
|
secp256k1_num_mul(&bnt2, &bnc2, &c->a2); |
||||
|
secp256k1_num_add(&bnt1, &bnt1, &bnt2); |
||||
|
secp256k1_num_sub(r1, a, &bnt1); |
||||
|
secp256k1_num_mul(&bnt1, &bnc1, &c->b1); |
||||
|
secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2); |
||||
|
secp256k1_num_sub(r2, &bnt1, &bnt2); |
||||
|
|
||||
|
secp256k1_num_free(&bnc1); |
||||
|
secp256k1_num_free(&bnc2); |
||||
|
secp256k1_num_free(&bnt1); |
||||
|
secp256k1_num_free(&bnt2); |
||||
|
secp256k1_num_free(&bnn2); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
void static secp256k1_ge_start(void) { |
||||
|
static const unsigned char secp256k1_ge_consts_order[] = { |
||||
|
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 |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_g_x[] = { |
||||
|
0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC, |
||||
|
0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07, |
||||
|
0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9, |
||||
|
0x59,0xF2,0x81,0x5B,0x16,0xF8,0x17,0x98 |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_g_y[] = { |
||||
|
0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65, |
||||
|
0x5D,0xA4,0xFB,0xFC,0x0E,0x11,0x08,0xA8, |
||||
|
0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19, |
||||
|
0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8 |
||||
|
}; |
||||
|
#ifdef USE_ENDOMORPHISM |
||||
|
// properties of secp256k1's efficiently computable endomorphism
|
||||
|
static const unsigned char secp256k1_ge_consts_lambda[] = { |
||||
|
0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0, |
||||
|
0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, |
||||
|
0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78, |
||||
|
0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72 |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_beta[] = { |
||||
|
0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10, |
||||
|
0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9, |
||||
|
0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95, |
||||
|
0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_a1b2[] = { |
||||
|
0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd, |
||||
|
0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15 |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_b1[] = { |
||||
|
0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28, |
||||
|
0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3 |
||||
|
}; |
||||
|
static const unsigned char secp256k1_ge_consts_a2[] = { |
||||
|
0x01, |
||||
|
0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, |
||||
|
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 |
||||
|
}; |
||||
|
#endif |
||||
|
if (secp256k1_ge_consts == NULL) { |
||||
|
secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t)); |
||||
|
secp256k1_num_init(&ret->order); |
||||
|
secp256k1_num_init(&ret->half_order); |
||||
|
secp256k1_num_set_bin(&ret->order, secp256k1_ge_consts_order, sizeof(secp256k1_ge_consts_order)); |
||||
|
secp256k1_num_copy(&ret->half_order, &ret->order); |
||||
|
secp256k1_num_shift(&ret->half_order, 1); |
||||
|
#ifdef USE_ENDOMORPHISM |
||||
|
secp256k1_num_init(&ret->lambda); |
||||
|
secp256k1_num_init(&ret->a1b2); |
||||
|
secp256k1_num_init(&ret->a2); |
||||
|
secp256k1_num_init(&ret->b1); |
||||
|
secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda)); |
||||
|
secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2)); |
||||
|
secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2)); |
||||
|
secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1)); |
||||
|
secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta); |
||||
|
#endif |
||||
|
secp256k1_fe_t g_x, g_y; |
||||
|
secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x); |
||||
|
secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y); |
||||
|
secp256k1_ge_set_xy(&ret->g, &g_x, &g_y); |
||||
|
secp256k1_ge_consts = ret; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_ge_stop(void) { |
||||
|
if (secp256k1_ge_consts != NULL) { |
||||
|
secp256k1_ge_consts_t *c = (secp256k1_ge_consts_t*)secp256k1_ge_consts; |
||||
|
secp256k1_num_free(&c->order); |
||||
|
secp256k1_num_free(&c->half_order); |
||||
|
secp256k1_num_free(&c->lambda); |
||||
|
secp256k1_num_free(&c->a1b2); |
||||
|
secp256k1_num_free(&c->a2); |
||||
|
secp256k1_num_free(&c->b1); |
||||
|
free((void*)c); |
||||
|
secp256k1_ge_consts = NULL; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,18 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_IMPL_H_ |
||||
|
#define _SECP256K1_NUM_IMPL_H_ |
||||
|
|
||||
|
#include "../num.h" |
||||
|
|
||||
|
#if defined(USE_NUM_GMP) |
||||
|
#include "num_gmp.h" |
||||
|
#elif defined(USE_NUM_OPENSSL) |
||||
|
#include "num_openssl.h" |
||||
|
#else |
||||
|
#error "Please select num implementation" |
||||
|
#endif |
||||
|
|
||||
|
#endif |
@ -0,0 +1,346 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_REPR_IMPL_H_ |
||||
|
#define _SECP256K1_NUM_REPR_IMPL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <gmp.h> |
||||
|
|
||||
|
#include "num.h" |
||||
|
|
||||
|
#ifdef VERIFY |
||||
|
void static secp256k1_num_sanity(const secp256k1_num_t *a) { |
||||
|
assert(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); |
||||
|
} |
||||
|
#else |
||||
|
#define secp256k1_num_sanity(a) do { } while(0) |
||||
|
#endif |
||||
|
|
||||
|
void static secp256k1_num_init(secp256k1_num_t *r) { |
||||
|
r->neg = 0; |
||||
|
r->limbs = 1; |
||||
|
r->data[0] = 0; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_free(secp256k1_num_t *r) { |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { |
||||
|
*r = *a; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_bits(const secp256k1_num_t *a) { |
||||
|
int ret=(a->limbs-1)*GMP_NUMB_BITS; |
||||
|
mp_limb_t x=a->data[a->limbs-1]; |
||||
|
while (x) { |
||||
|
x >>= 1; |
||||
|
ret++; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { |
||||
|
unsigned char tmp[65]; |
||||
|
int len = 0; |
||||
|
if (a->limbs>1 || a->data[0] != 0) { |
||||
|
len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); |
||||
|
} |
||||
|
int shift = 0; |
||||
|
while (shift < len && tmp[shift] == 0) shift++; |
||||
|
assert(len-shift <= rlen); |
||||
|
memset(r, 0, rlen - len + shift); |
||||
|
if (len > shift) |
||||
|
memcpy(r + rlen - len + shift, tmp + shift, len - shift); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) { |
||||
|
assert(alen > 0); |
||||
|
assert(alen <= 64); |
||||
|
int len = mpn_set_str(r->data, a, alen, 256); |
||||
|
assert(len <= NUM_LIMBS*2); |
||||
|
r->limbs = len; |
||||
|
r->neg = 0; |
||||
|
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_int(secp256k1_num_t *r, int a) { |
||||
|
r->limbs = 1; |
||||
|
r->neg = (a < 0); |
||||
|
r->data[0] = (a < 0) ? -a : a; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); |
||||
|
r->limbs = a->limbs; |
||||
|
if (c != 0) { |
||||
|
assert(r->limbs < 2*NUM_LIMBS); |
||||
|
r->data[r->limbs++] = c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); |
||||
|
assert(c == 0); |
||||
|
r->limbs = a->limbs; |
||||
|
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) { |
||||
|
secp256k1_num_sanity(r); |
||||
|
secp256k1_num_sanity(m); |
||||
|
|
||||
|
if (r->limbs >= m->limbs) { |
||||
|
mp_limb_t t[2*NUM_LIMBS]; |
||||
|
mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); |
||||
|
r->limbs = m->limbs; |
||||
|
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; |
||||
|
} |
||||
|
|
||||
|
if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { |
||||
|
secp256k1_num_sub_abs(r, m, r); |
||||
|
r->neg = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) { |
||||
|
secp256k1_num_sanity(a); |
||||
|
secp256k1_num_sanity(m); |
||||
|
|
||||
|
// mpn_gcdext computes: (G,S) = gcdext(U,V), where
|
||||
|
// * G = gcd(U,V)
|
||||
|
// * G = U*S + V*T
|
||||
|
// * U has equal or more limbs than V, and V has no padding
|
||||
|
// If we set U to be (a padded version of) a, and V = m:
|
||||
|
// G = a*S + m*T
|
||||
|
// G = a*S mod m
|
||||
|
// Assuming G=1:
|
||||
|
// S = 1/a mod m
|
||||
|
assert(m->limbs <= NUM_LIMBS); |
||||
|
assert(m->data[m->limbs-1] != 0); |
||||
|
mp_limb_t g[NUM_LIMBS+1]; |
||||
|
mp_limb_t u[NUM_LIMBS+1]; |
||||
|
mp_limb_t v[NUM_LIMBS+1]; |
||||
|
for (int i=0; i < m->limbs; i++) { |
||||
|
u[i] = (i < a->limbs) ? a->data[i] : 0; |
||||
|
v[i] = m->data[i]; |
||||
|
} |
||||
|
mp_size_t sn = NUM_LIMBS+1; |
||||
|
mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); |
||||
|
assert(gn == 1); |
||||
|
assert(g[0] == 1); |
||||
|
r->neg = a->neg ^ m->neg; |
||||
|
if (sn < 0) { |
||||
|
mpn_sub(r->data, m->data, m->limbs, r->data, -sn); |
||||
|
r->limbs = m->limbs; |
||||
|
while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; |
||||
|
} else { |
||||
|
r->limbs = sn; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_zero(const secp256k1_num_t *a) { |
||||
|
return (a->limbs == 1 && a->data[0] == 0); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_odd(const secp256k1_num_t *a) { |
||||
|
return a->data[0] & 1; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_neg(const secp256k1_num_t *a) { |
||||
|
return (a->limbs > 1 || a->data[0] != 0) && a->neg; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
if (a->limbs > b->limbs) return 1; |
||||
|
if (a->limbs < b->limbs) return -1; |
||||
|
return mpn_cmp(a->data, b->data, a->limbs); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) { |
||||
|
if (!(b->neg ^ bneg ^ a->neg)) { // a and b have the same sign
|
||||
|
r->neg = a->neg; |
||||
|
if (a->limbs >= b->limbs) { |
||||
|
secp256k1_num_add_abs(r, a, b); |
||||
|
} else { |
||||
|
secp256k1_num_add_abs(r, b, a); |
||||
|
} |
||||
|
} else { |
||||
|
if (secp256k1_num_cmp(a, b) > 0) { |
||||
|
r->neg = a->neg; |
||||
|
secp256k1_num_sub_abs(r, a, b); |
||||
|
} else { |
||||
|
r->neg = b->neg ^ bneg; |
||||
|
secp256k1_num_sub_abs(r, b, a); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
secp256k1_num_sanity(a); |
||||
|
secp256k1_num_sanity(b); |
||||
|
secp256k1_num_subadd(r, a, b, 0); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
secp256k1_num_sanity(a); |
||||
|
secp256k1_num_sanity(b); |
||||
|
secp256k1_num_subadd(r, a, b, 1); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
secp256k1_num_sanity(a); |
||||
|
secp256k1_num_sanity(b); |
||||
|
|
||||
|
mp_limb_t tmp[2*NUM_LIMBS+1]; |
||||
|
assert(a->limbs + b->limbs <= 2*NUM_LIMBS+1); |
||||
|
if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { |
||||
|
r->limbs = 1; |
||||
|
r->neg = 0; |
||||
|
r->data[0] = 0; |
||||
|
return; |
||||
|
} |
||||
|
if (a->limbs >= b->limbs) |
||||
|
mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); |
||||
|
else |
||||
|
mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); |
||||
|
r->limbs = a->limbs + b->limbs; |
||||
|
if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--; |
||||
|
assert(r->limbs <= 2*NUM_LIMBS); |
||||
|
mpn_copyi(r->data, tmp, r->limbs); |
||||
|
r->neg = a->neg ^ b->neg; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
secp256k1_num_sanity(a); |
||||
|
secp256k1_num_sanity(b); |
||||
|
if (b->limbs > a->limbs) { |
||||
|
r->limbs = 1; |
||||
|
r->data[0] = 0; |
||||
|
r->neg = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
mp_limb_t quo[2*NUM_LIMBS+1]; |
||||
|
mp_limb_t rem[2*NUM_LIMBS+1]; |
||||
|
mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs); |
||||
|
mpn_copyi(r->data, quo, a->limbs - b->limbs + 1); |
||||
|
r->limbs = a->limbs - b->limbs + 1; |
||||
|
while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--; |
||||
|
r->neg = a->neg ^ b->neg; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { |
||||
|
secp256k1_num_mul(r, a, b); |
||||
|
secp256k1_num_mod(r, m); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int static secp256k1_num_shift(secp256k1_num_t *r, int bits) { |
||||
|
assert(bits <= GMP_NUMB_BITS); |
||||
|
mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits); |
||||
|
if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--; |
||||
|
ret >>= (GMP_NUMB_BITS - bits); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { |
||||
|
return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_inc(secp256k1_num_t *r) { |
||||
|
mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1); |
||||
|
if (ret) { |
||||
|
assert(r->limbs < 2*NUM_LIMBS); |
||||
|
r->data[r->limbs++] = ret; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { |
||||
|
static const unsigned char cvt[256] = { |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, |
||||
|
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, |
||||
|
0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0 |
||||
|
}; |
||||
|
char num[257] = {}; |
||||
|
for (int i=0; i<alen; i++) { |
||||
|
num[i] = cvt[a[i]]; |
||||
|
} |
||||
|
r->limbs = mpn_set_str(r->data, num, alen, 16); |
||||
|
while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { |
||||
|
static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; |
||||
|
unsigned char *tmp = malloc(257); |
||||
|
mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs); |
||||
|
assert(len <= rlen); |
||||
|
for (int i=0; i<len; i++) { |
||||
|
assert(rlen-len+i >= 0); |
||||
|
assert(rlen-len+i < rlen); |
||||
|
assert(tmp[i] >= 0); |
||||
|
assert(tmp[i] < 16); |
||||
|
r[rlen-len+i] = cvt[tmp[i]]; |
||||
|
} |
||||
|
for (int i=0; i<rlen-len; i++) { |
||||
|
assert(i >= 0); |
||||
|
assert(i < rlen); |
||||
|
r[i] = cvt[0]; |
||||
|
} |
||||
|
free(tmp); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { |
||||
|
assert(bits > 0); |
||||
|
rh->neg = a->neg; |
||||
|
if (bits >= a->limbs * GMP_NUMB_BITS) { |
||||
|
*rl = *a; |
||||
|
rh->limbs = 1; |
||||
|
rh->data[0] = 0; |
||||
|
return; |
||||
|
} |
||||
|
rl->limbs = 0; |
||||
|
rl->neg = a->neg; |
||||
|
int left = bits; |
||||
|
while (left >= GMP_NUMB_BITS) { |
||||
|
rl->data[rl->limbs] = a->data[rl->limbs]; |
||||
|
rl->limbs++; |
||||
|
left -= GMP_NUMB_BITS; |
||||
|
} |
||||
|
if (left == 0) { |
||||
|
mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs); |
||||
|
rh->limbs = a->limbs - rl->limbs; |
||||
|
} else { |
||||
|
mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left); |
||||
|
rh->limbs = a->limbs - rl->limbs; |
||||
|
while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--; |
||||
|
} |
||||
|
if (left > 0) { |
||||
|
rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1); |
||||
|
rl->limbs++; |
||||
|
} |
||||
|
while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--; |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_negate(secp256k1_num_t *r) { |
||||
|
r->neg ^= 1; |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,145 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_REPR_IMPL_H_ |
||||
|
#define _SECP256K1_NUM_REPR_IMPL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <openssl/bn.h> |
||||
|
#include <openssl/crypto.h> |
||||
|
|
||||
|
#include "../num.h" |
||||
|
|
||||
|
void static secp256k1_num_init(secp256k1_num_t *r) { |
||||
|
BN_init(&r->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_free(secp256k1_num_t *r) { |
||||
|
BN_free(&r->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { |
||||
|
BN_copy(&r->bn, &a->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { |
||||
|
unsigned int size = BN_num_bytes(&a->bn); |
||||
|
assert(size <= rlen); |
||||
|
memset(r,0,rlen); |
||||
|
BN_bn2bin(&a->bn, r + rlen - size); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) { |
||||
|
BN_bin2bn(a, alen, &r->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_int(secp256k1_num_t *r, int a) { |
||||
|
BN_set_word(&r->bn, a < 0 ? -a : a); |
||||
|
BN_set_negative(&r->bn, a < 0); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) { |
||||
|
BN_CTX *ctx = BN_CTX_new(); |
||||
|
BN_mod_inverse(&r->bn, &a->bn, &m->bn, ctx); |
||||
|
BN_CTX_free(ctx); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { |
||||
|
BN_CTX *ctx = BN_CTX_new(); |
||||
|
BN_mod_mul(&r->bn, &a->bn, &b->bn, &m->bn, ctx); |
||||
|
BN_CTX_free(ctx); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
return BN_cmp(&a->bn, &b->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
BN_add(&r->bn, &a->bn, &b->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
BN_sub(&r->bn, &a->bn, &b->bn); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
BN_CTX *ctx = BN_CTX_new(); |
||||
|
BN_mul(&r->bn, &a->bn, &b->bn, ctx); |
||||
|
BN_CTX_free(ctx); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { |
||||
|
BN_CTX *ctx = BN_CTX_new(); |
||||
|
BN_div(&r->bn, NULL, &a->bn, &b->bn, ctx); |
||||
|
BN_CTX_free(ctx); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) { |
||||
|
BN_CTX *ctx = BN_CTX_new(); |
||||
|
BN_nnmod(&r->bn, &r->bn, &m->bn, ctx); |
||||
|
BN_CTX_free(ctx); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_bits(const secp256k1_num_t *a) { |
||||
|
return BN_num_bits(&a->bn); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_shift(secp256k1_num_t *r, int bits) { |
||||
|
int ret = BN_is_zero(&r->bn) ? 0 : r->bn.d[0] & ((1 << bits) - 1); |
||||
|
BN_rshift(&r->bn, &r->bn, bits); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_zero(const secp256k1_num_t *a) { |
||||
|
return BN_is_zero(&a->bn); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_odd(const secp256k1_num_t *a) { |
||||
|
return BN_is_odd(&a->bn); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_is_neg(const secp256k1_num_t *a) { |
||||
|
return BN_is_negative(&a->bn); |
||||
|
} |
||||
|
|
||||
|
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { |
||||
|
return BN_is_bit_set(&a->bn, pos); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_inc(secp256k1_num_t *r) { |
||||
|
BN_add_word(&r->bn, 1); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { |
||||
|
char *str = (char*)malloc(alen+1); |
||||
|
memcpy(str, a, alen); |
||||
|
str[alen] = 0; |
||||
|
BIGNUM *pbn = &r->bn; |
||||
|
BN_hex2bn(&pbn, str); |
||||
|
free(str); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { |
||||
|
char *str = BN_bn2hex(&a->bn); |
||||
|
int len = strlen(str); |
||||
|
assert(rlen >= len); |
||||
|
for (int i=0; i<rlen-len; i++) |
||||
|
r[i] = '0'; |
||||
|
memcpy(r+rlen-len, str, len); |
||||
|
OPENSSL_free(str); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { |
||||
|
BN_copy(&rl->bn, &a->bn); |
||||
|
BN_rshift(&rh->bn, &a->bn, bits); |
||||
|
BN_mask_bits(&rl->bn, bits); |
||||
|
} |
||||
|
|
||||
|
void static secp256k1_num_negate(secp256k1_num_t *r) { |
||||
|
BN_set_negative(&r->bn, !BN_is_negative(&r->bn)); |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,45 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_UTIL_IMPL_H_ |
||||
|
#define _SECP256K1_UTIL_IMPL_H_ |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "../util.h" |
||||
|
|
||||
|
static inline uint32_t secp256k1_rand32(void) { |
||||
|
static uint32_t Rz = 11, Rw = 11; |
||||
|
Rz = 36969 * (Rz & 0xFFFF) + (Rz >> 16); |
||||
|
Rw = 18000 * (Rw & 0xFFFF) + (Rw >> 16); |
||||
|
return (Rw << 16) + (Rw >> 16) + Rz; |
||||
|
} |
||||
|
|
||||
|
static void secp256k1_rand256(unsigned char *b32) { |
||||
|
for (int i=0; i<8; i++) { |
||||
|
uint32_t r = secp256k1_rand32(); |
||||
|
b32[i*4 + 0] = (r >> 0) & 0xFF; |
||||
|
b32[i*4 + 1] = (r >> 8) & 0xFF; |
||||
|
b32[i*4 + 2] = (r >> 16) & 0xFF; |
||||
|
b32[i*4 + 3] = (r >> 24) & 0xFF; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void secp256k1_rand256_test(unsigned char *b32) { |
||||
|
int bits=0; |
||||
|
memset(b32, 0, 32); |
||||
|
while (bits < 256) { |
||||
|
uint32_t ent = secp256k1_rand32(); |
||||
|
int now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31; |
||||
|
uint32_t val = 1 & (ent >> 11); |
||||
|
while (now > 0 && bits < 256) { |
||||
|
b32[bits / 8] |= val << (bits % 8); |
||||
|
now--; |
||||
|
bits++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,93 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_ |
||||
|
#define _SECP256K1_NUM_ |
||||
|
|
||||
|
#if defined(USE_NUM_GMP) |
||||
|
#include "num_gmp.h" |
||||
|
#elif defined(USE_NUM_OPENSSL) |
||||
|
#include "num_openssl.h" |
||||
|
#else |
||||
|
#error "Please select num implementation" |
||||
|
#endif |
||||
|
|
||||
|
/** Initialize a number. */ |
||||
|
void static secp256k1_num_init(secp256k1_num_t *r); |
||||
|
|
||||
|
/** Free a number. */ |
||||
|
void static secp256k1_num_free(secp256k1_num_t *r); |
||||
|
|
||||
|
/** Copy a number. */ |
||||
|
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Convert a number's absolute value to a binary big-endian string.
|
||||
|
* There must be enough place. */ |
||||
|
void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Set a number to the value of a binary big-endian string. */ |
||||
|
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen); |
||||
|
|
||||
|
/** Set a number equal to a (signed) integer. */ |
||||
|
void static secp256k1_num_set_int(secp256k1_num_t *r, int a); |
||||
|
|
||||
|
/** Compute a modular inverse. The input must be less than the modulus. */ |
||||
|
void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m); |
||||
|
|
||||
|
/** Multiply two numbers modulo another. */ |
||||
|
void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m); |
||||
|
|
||||
|
/** Compare the absolute value of two numbers. */ |
||||
|
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b); |
||||
|
|
||||
|
/** Add two (signed) numbers. */ |
||||
|
void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); |
||||
|
|
||||
|
/** Subtract two (signed) numbers. */ |
||||
|
void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); |
||||
|
|
||||
|
/** Multiply two (signed) numbers. */ |
||||
|
void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); |
||||
|
|
||||
|
/** Divide two (signed) numbers. */ |
||||
|
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); |
||||
|
|
||||
|
/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1,
|
||||
|
even if r was negative. */ |
||||
|
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m); |
||||
|
|
||||
|
/** Calculate the number of bits in (the absolute value of) a number. */ |
||||
|
int static secp256k1_num_bits(const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Right-shift the passed number by bits bits, and return those bits. */ |
||||
|
int static secp256k1_num_shift(secp256k1_num_t *r, int bits); |
||||
|
|
||||
|
/** Check whether a number is zero. */ |
||||
|
int static secp256k1_num_is_zero(const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Check whether a number is odd. */ |
||||
|
int static secp256k1_num_is_odd(const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Check whether a number is strictly negative. */ |
||||
|
int static secp256k1_num_is_neg(const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Check whether a particular bit is set in a number. */ |
||||
|
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos); |
||||
|
|
||||
|
/** Increase a number by 1. */ |
||||
|
void static secp256k1_num_inc(secp256k1_num_t *r); |
||||
|
|
||||
|
/** Set a number equal to the value of a hex string (unsigned). */ |
||||
|
void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen); |
||||
|
|
||||
|
/** Convert (the absolute value of) a number to a hexadecimal string. */ |
||||
|
void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a); |
||||
|
|
||||
|
/** Split a number into a low and high part. */ |
||||
|
void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits); |
||||
|
|
||||
|
/** Change a number's sign. */ |
||||
|
void static secp256k1_num_negate(secp256k1_num_t *r); |
||||
|
|
||||
|
#endif |
@ -0,0 +1,18 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_REPR_ |
||||
|
#define _SECP256K1_NUM_REPR_ |
||||
|
|
||||
|
#include <gmp.h> |
||||
|
|
||||
|
#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) |
||||
|
|
||||
|
typedef struct { |
||||
|
mp_limb_t data[2*NUM_LIMBS]; |
||||
|
int neg; |
||||
|
int limbs; |
||||
|
} secp256k1_num_t; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,14 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_NUM_REPR_ |
||||
|
#define _SECP256K1_NUM_REPR_ |
||||
|
|
||||
|
#include <openssl/bn.h> |
||||
|
|
||||
|
typedef struct { |
||||
|
BIGNUM bn; |
||||
|
} secp256k1_num_t; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,269 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#include "impl/num.h" |
||||
|
#include "impl/field.h" |
||||
|
#include "impl/group.h" |
||||
|
#include "impl/ecmult.h" |
||||
|
#include "impl/ecdsa.h" |
||||
|
|
||||
|
void secp256k1_start(void) { |
||||
|
secp256k1_fe_start(); |
||||
|
secp256k1_ge_start(); |
||||
|
secp256k1_ecmult_start(); |
||||
|
} |
||||
|
|
||||
|
void secp256k1_stop(void) { |
||||
|
secp256k1_ecmult_stop(); |
||||
|
secp256k1_ge_stop(); |
||||
|
secp256k1_fe_stop(); |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) { |
||||
|
int ret = -3; |
||||
|
secp256k1_num_t m; |
||||
|
secp256k1_num_init(&m); |
||||
|
secp256k1_ecdsa_sig_t s; |
||||
|
secp256k1_ecdsa_sig_init(&s); |
||||
|
secp256k1_ge_t q; |
||||
|
secp256k1_num_set_bin(&m, msg, msglen); |
||||
|
|
||||
|
if (!secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen)) { |
||||
|
ret = -1; |
||||
|
goto end; |
||||
|
} |
||||
|
if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { |
||||
|
ret = -2; |
||||
|
goto end; |
||||
|
} |
||||
|
if (!secp256k1_ecdsa_sig_verify(&s, &q, &m)) { |
||||
|
ret = 0; |
||||
|
goto end; |
||||
|
} |
||||
|
ret = 1; |
||||
|
end: |
||||
|
secp256k1_ecdsa_sig_free(&s); |
||||
|
secp256k1_num_free(&m); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) { |
||||
|
secp256k1_num_t sec, non, msg; |
||||
|
secp256k1_num_init(&sec); |
||||
|
secp256k1_num_init(&non); |
||||
|
secp256k1_num_init(&msg); |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
secp256k1_num_set_bin(&non, nonce, 32); |
||||
|
secp256k1_num_set_bin(&msg, message, messagelen); |
||||
|
secp256k1_ecdsa_sig_t sig; |
||||
|
secp256k1_ecdsa_sig_init(&sig); |
||||
|
int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL); |
||||
|
if (ret) { |
||||
|
secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); |
||||
|
} |
||||
|
secp256k1_ecdsa_sig_free(&sig); |
||||
|
secp256k1_num_free(&msg); |
||||
|
secp256k1_num_free(&non); |
||||
|
secp256k1_num_free(&sec); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { |
||||
|
secp256k1_num_t sec, non, msg; |
||||
|
secp256k1_num_init(&sec); |
||||
|
secp256k1_num_init(&non); |
||||
|
secp256k1_num_init(&msg); |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
secp256k1_num_set_bin(&non, nonce, 32); |
||||
|
secp256k1_num_set_bin(&msg, message, messagelen); |
||||
|
secp256k1_ecdsa_sig_t sig; |
||||
|
secp256k1_ecdsa_sig_init(&sig); |
||||
|
int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); |
||||
|
if (ret) { |
||||
|
secp256k1_num_get_bin(sig64, 32, &sig.r); |
||||
|
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); |
||||
|
} |
||||
|
secp256k1_ecdsa_sig_free(&sig); |
||||
|
secp256k1_num_free(&msg); |
||||
|
secp256k1_num_free(&non); |
||||
|
secp256k1_num_free(&sec); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) { |
||||
|
int ret = 0; |
||||
|
secp256k1_num_t m; |
||||
|
secp256k1_num_init(&m); |
||||
|
secp256k1_ecdsa_sig_t sig; |
||||
|
secp256k1_ecdsa_sig_init(&sig); |
||||
|
secp256k1_num_set_bin(&sig.r, sig64, 32); |
||||
|
secp256k1_num_set_bin(&sig.s, sig64 + 32, 32); |
||||
|
secp256k1_num_set_bin(&m, msg, msglen); |
||||
|
|
||||
|
secp256k1_ge_t q; |
||||
|
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { |
||||
|
secp256k1_ecdsa_pubkey_serialize(&q, pubkey, pubkeylen, compressed); |
||||
|
ret = 1; |
||||
|
} |
||||
|
secp256k1_ecdsa_sig_free(&sig); |
||||
|
secp256k1_num_free(&m); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) { |
||||
|
secp256k1_num_t sec; |
||||
|
secp256k1_num_init(&sec); |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
int ret = !secp256k1_num_is_zero(&sec) && |
||||
|
(secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0); |
||||
|
secp256k1_num_free(&sec); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { |
||||
|
secp256k1_ge_t q; |
||||
|
return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen); |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { |
||||
|
secp256k1_num_t sec; |
||||
|
secp256k1_num_init(&sec); |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
secp256k1_gej_t pj; |
||||
|
secp256k1_ecmult_gen(&pj, &sec); |
||||
|
secp256k1_ge_t p; |
||||
|
secp256k1_ge_set_gej(&p, &pj); |
||||
|
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { |
||||
|
secp256k1_ge_t p; |
||||
|
if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, *pubkeylen)) |
||||
|
return 0; |
||||
|
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0); |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { |
||||
|
int ret = 1; |
||||
|
secp256k1_num_t term; |
||||
|
secp256k1_num_init(&term); |
||||
|
secp256k1_num_set_bin(&term, tweak, 32); |
||||
|
if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) |
||||
|
ret = 0; |
||||
|
secp256k1_num_t sec; |
||||
|
secp256k1_num_init(&sec); |
||||
|
if (ret) { |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
secp256k1_num_add(&sec, &sec, &term); |
||||
|
secp256k1_num_mod(&sec, &secp256k1_ge_consts->order); |
||||
|
if (secp256k1_num_is_zero(&sec)) |
||||
|
ret = 0; |
||||
|
} |
||||
|
if (ret) |
||||
|
secp256k1_num_get_bin(seckey, 32, &sec); |
||||
|
secp256k1_num_free(&sec); |
||||
|
secp256k1_num_free(&term); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { |
||||
|
int ret = 1; |
||||
|
secp256k1_num_t term; |
||||
|
secp256k1_num_init(&term); |
||||
|
secp256k1_num_set_bin(&term, tweak, 32); |
||||
|
if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) |
||||
|
ret = 0; |
||||
|
secp256k1_ge_t p; |
||||
|
if (ret) { |
||||
|
if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) |
||||
|
ret = 0; |
||||
|
} |
||||
|
if (ret) { |
||||
|
secp256k1_gej_t pt; |
||||
|
secp256k1_ecmult_gen(&pt, &term); |
||||
|
secp256k1_gej_add_ge(&pt, &pt, &p); |
||||
|
if (secp256k1_gej_is_infinity(&pt)) |
||||
|
ret = 0; |
||||
|
secp256k1_ge_set_gej(&p, &pt); |
||||
|
int oldlen = pubkeylen; |
||||
|
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); |
||||
|
assert(pubkeylen == oldlen); |
||||
|
} |
||||
|
secp256k1_num_free(&term); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { |
||||
|
int ret = 1; |
||||
|
secp256k1_num_t factor; |
||||
|
secp256k1_num_init(&factor); |
||||
|
secp256k1_num_set_bin(&factor, tweak, 32); |
||||
|
if (secp256k1_num_is_zero(&factor)) |
||||
|
ret = 0; |
||||
|
if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) |
||||
|
ret = 0; |
||||
|
secp256k1_num_t sec; |
||||
|
secp256k1_num_init(&sec); |
||||
|
if (ret) { |
||||
|
secp256k1_num_set_bin(&sec, seckey, 32); |
||||
|
secp256k1_num_mod_mul(&sec, &sec, &factor, &secp256k1_ge_consts->order); |
||||
|
} |
||||
|
if (ret) |
||||
|
secp256k1_num_get_bin(seckey, 32, &sec); |
||||
|
secp256k1_num_free(&sec); |
||||
|
secp256k1_num_free(&factor); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { |
||||
|
int ret = 1; |
||||
|
secp256k1_num_t factor; |
||||
|
secp256k1_num_init(&factor); |
||||
|
secp256k1_num_set_bin(&factor, tweak, 32); |
||||
|
if (secp256k1_num_is_zero(&factor)) |
||||
|
ret = 0; |
||||
|
if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) |
||||
|
ret = 0; |
||||
|
secp256k1_ge_t p; |
||||
|
if (ret) { |
||||
|
if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) |
||||
|
ret = 0; |
||||
|
} |
||||
|
if (ret) { |
||||
|
secp256k1_num_t zero; |
||||
|
secp256k1_num_init(&zero); |
||||
|
secp256k1_num_set_int(&zero, 0); |
||||
|
secp256k1_gej_t pt; |
||||
|
secp256k1_gej_set_ge(&pt, &p); |
||||
|
secp256k1_ecmult(&pt, &pt, &factor, &zero); |
||||
|
secp256k1_num_free(&zero); |
||||
|
secp256k1_ge_set_gej(&p, &pt); |
||||
|
int oldlen = pubkeylen; |
||||
|
secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); |
||||
|
assert(pubkeylen == oldlen); |
||||
|
} |
||||
|
secp256k1_num_free(&factor); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { |
||||
|
secp256k1_num_t key; |
||||
|
secp256k1_num_init(&key); |
||||
|
secp256k1_num_set_bin(&key, seckey, 32); |
||||
|
int ret = secp256k1_ecdsa_privkey_serialize(privkey, privkeylen, &key, compressed); |
||||
|
secp256k1_num_free(&key); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { |
||||
|
secp256k1_num_t key; |
||||
|
secp256k1_num_init(&key); |
||||
|
int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen); |
||||
|
if (ret) |
||||
|
secp256k1_num_get_bin(seckey, 32, &key); |
||||
|
secp256k1_num_free(&key); |
||||
|
return ret; |
||||
|
} |
@ -0,0 +1,121 @@ |
|||||
|
#ifndef _SECP256K1_ |
||||
|
#define _SECP256K1_ |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C" { |
||||
|
#endif |
||||
|
|
||||
|
/** 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(void); |
||||
|
|
||||
|
/** 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 |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, |
||||
|
const unsigned char *sig, int siglen, |
||||
|
const unsigned char *pubkey, int pubkeylen); |
||||
|
|
||||
|
/** Create an ECDSA signature.
|
||||
|
* Returns: 1: signature created |
||||
|
* 0: nonce invalid, try another one |
||||
|
* In: msg: the message being signed |
||||
|
* msglen: the length of the message being signed |
||||
|
* seckey: pointer to a 32-byte secret key (assumed to be valid) |
||||
|
* nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG) |
||||
|
* Out: sig: pointer to a 72-byte array where the signature will be placed. |
||||
|
* siglen: pointer to an int, which will be updated to the signature length (<=72). |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, |
||||
|
unsigned char *sig, int *siglen, |
||||
|
const unsigned char *seckey, |
||||
|
const unsigned char *nonce); |
||||
|
|
||||
|
/** Create a compact ECDSA signature (64 byte + recovery id).
|
||||
|
* Returns: 1: signature created |
||||
|
* 0: nonce invalid, try another one |
||||
|
* In: msg: the message being signed |
||||
|
* msglen: the length of the message being signed |
||||
|
* seckey: pointer to a 32-byte secret key (assumed to be valid) |
||||
|
* nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG) |
||||
|
* Out: sig: pointer to a 64-byte array where the signature will be placed. |
||||
|
* recid: pointer to an int, which will be updated to contain the recovery id. |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, |
||||
|
unsigned char *sig64, |
||||
|
const unsigned char *seckey, |
||||
|
const unsigned char *nonce, |
||||
|
int *recid); |
||||
|
|
||||
|
/** Recover an ECDSA public key from a compact signature.
|
||||
|
* Returns: 1: public key succesfully recovered (which guarantees a correct signature). |
||||
|
* 0: otherwise. |
||||
|
* In: msg: the message assumed to be signed |
||||
|
* msglen: the length of the message |
||||
|
* sig64: signature as 64 byte array |
||||
|
* compressed: whether to recover a compressed or uncompressed pubkey |
||||
|
* recid: the recovery id (as returned by ecdsa_sign_compact) |
||||
|
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey. |
||||
|
* pubkeylen: pointer to an int that will contain the pubkey length. |
||||
|
*/ |
||||
|
|
||||
|
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, |
||||
|
const unsigned char *sig64, |
||||
|
unsigned char *pubkey, int *pubkeylen, |
||||
|
int compressed, int recid); |
||||
|
|
||||
|
/** 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 |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey); |
||||
|
|
||||
|
/** Just validate a public key.
|
||||
|
* Returns: 1: valid public key |
||||
|
* 0: invalid public key |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); |
||||
|
|
||||
|
/** 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. |
||||
|
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) |
||||
|
* area to store the public key. |
||||
|
* pubkeylen: pointer to int that will be updated to contains the pubkey's |
||||
|
* length. |
||||
|
* Returns: 1: secret was valid, public key stores |
||||
|
* 0: secret was invalid, try again. |
||||
|
*/ |
||||
|
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); |
||||
|
|
||||
|
int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, |
||||
|
unsigned char *privkey, int *privkeylen, |
||||
|
int compressed); |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_import(unsigned char *seckey, |
||||
|
const unsigned char *privkey, int privkeylen); |
||||
|
|
||||
|
int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak); |
||||
|
int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); |
||||
|
int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak); |
||||
|
int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#endif |
@ -0,0 +1,19 @@ |
|||||
|
// Copyright (c) 2013 Pieter Wuille
|
||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
||||
|
#ifndef _SECP256K1_UTIL_H_ |
||||
|
#define _SECP256K1_UTIL_H_ |
||||
|
|
||||
|
/** Generate a pseudorandom 32-bit number. */ |
||||
|
static uint32_t secp256k1_rand32(void); |
||||
|
|
||||
|
/** Generate a pseudorandom 32-byte array. */ |
||||
|
static void secp256k1_rand256(unsigned char *b32); |
||||
|
|
||||
|
/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ |
||||
|
static void secp256k1_rand256_test(unsigned char *b32); |
||||
|
|
||||
|
#include "impl/util.h" |
||||
|
|
||||
|
#endif |
Loading…
Reference in new issue