diff --git a/secp256k1/impl/num.h b/secp256k1/impl/num.h index fc6d05c3d..21e3390b5 100644 --- a/secp256k1/impl/num.h +++ b/secp256k1/impl/num.h @@ -11,6 +11,8 @@ #include "num_gmp.h" #elif defined(USE_NUM_OPENSSL) #include "num_openssl.h" +#elif defined(USE_NUM_BOOST) +#include "num_boost.h" #else #error "Please select num implementation" #endif diff --git a/secp256k1/impl/num_boost.h b/secp256k1/impl/num_boost.h new file mode 100644 index 000000000..b808e3214 --- /dev/null +++ b/secp256k1/impl/num_boost.h @@ -0,0 +1,212 @@ +// Copyright (c) 2014 Tim Hughes +// 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 +#include + +void static secp256k1_num_init(secp256k1_num_t *r) +{ + *r = 0; +} + +void static secp256k1_num_free(secp256k1_num_t*) +{ +} + +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 numLimbs = a->backend().size(); + int ret = (numLimbs - 1) * a->backend().limb_bits; + for (auto x = a->backend().limbs()[numLimbs - 1]; x; x >>= 1, ++ret); + return ret; +} + +void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) +{ + for (auto n = abs(*a); n; n >>= 8) + { + assert(rlen > 0); // out of space? + r[--rlen] = n.convert_to(); + } + memset(r, 0, rlen); +} + +void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) +{ + *r = 0; + for (unsigned int i = 0; i != alen; ++i) + { + *r <<= 8; + *r |= a[i]; + } +} + +void static secp256k1_num_set_int(secp256k1_num_t *r, int a) +{ + *r = a; +} + +void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) +{ + *r %= *m; +} + +void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *n, const secp256k1_num_t *m) +{ + // http://rosettacode.org/wiki/Modular_inverse + secp256k1_num_t a = *n; + secp256k1_num_t b = *m; + secp256k1_num_t x0 = 0; + secp256k1_num_t x1 = 1; + assert(*n > 0); + assert(*m > 0); + if (b != 1) + { + secp256k1_num_t q, t; + while (a > 1) + { + boost::multiprecision::divide_qr(a, b, q, t); + a = b; b = t; + + t = x1 - q * x0; + x1 = x0; x0 = t; + } + if (x1 < 0) + { + x1 += *m; + } + } + *r = x1; + + // check result + #ifdef _DEBUG + { + typedef boost::multiprecision::number> bignum; + bignum br = *r, bn = *n, bm = *m; + assert((((bn) * (br)) % bm) == 1); + } + #endif +} + +int static secp256k1_num_is_zero(const secp256k1_num_t *a) +{ + return a->is_zero(); +} + +int static secp256k1_num_is_odd(const secp256k1_num_t *a) +{ + return boost::multiprecision::bit_test(*a, 0); +} + +int static secp256k1_num_is_neg(const secp256k1_num_t *a) +{ + return a->backend().isneg(); +} + +int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) +{ + return a->backend().compare_unsigned(b->backend()); +} + +void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) +{ + *r = (*a) + (*b); +} + +void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) +{ + *r = (*a) - (*b); +} + +void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) +{ + *r = (*a) * (*b); +} + +void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) +{ + *r = (*a) / (*b); +} + +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) +{ + unsigned ret = r->convert_to() & ((1 << bits) - 1); + *r >>= bits; + return ret; +} + +int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) +{ + return boost::multiprecision::bit_test(*a, pos); +} + +void static secp256k1_num_inc(secp256k1_num_t *r) +{ + ++*r; +} + +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 + }; + *r = 0; + for (int i = 0; i != alen; ++i) + { + *r <<= 4; + *r |= cvt[a[i]]; + } +} + +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'}; + for (auto n = *a; n; n >>= 4) + { + assert(rlen > 0); // out of space? + r[--rlen] = cvt[n.convert_to() & 15]; + } + memset(r, '0', rlen); +} + +void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) +{ + *rl = *a & ((secp256k1_num_t(1) << bits) - 1); + *rh = *a >> bits; +} + +void static secp256k1_num_negate(secp256k1_num_t *r) +{ + r->backend().negate(); +} + +#endif diff --git a/secp256k1/num.h b/secp256k1/num.h index b2e7462bc..3fdd8f39d 100644 --- a/secp256k1/num.h +++ b/secp256k1/num.h @@ -9,6 +9,8 @@ #include "num_gmp.h" #elif defined(USE_NUM_OPENSSL) #include "num_openssl.h" +#elif defined(USE_NUM_BOOST) +#include "num_boost.h" #else #error "Please select num implementation" #endif diff --git a/secp256k1/num_boost.h b/secp256k1/num_boost.h new file mode 100644 index 000000000..2c9e49aee --- /dev/null +++ b/secp256k1/num_boost.h @@ -0,0 +1,12 @@ +// 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 + +typedef boost::multiprecision::number> secp256k1_num_t ; + +#endif diff --git a/secp256k1/secp256k1.c b/secp256k1/secp256k1.c index ed8bf2e95..b9b57d4a4 100644 --- a/secp256k1/secp256k1.c +++ b/secp256k1/secp256k1.c @@ -8,6 +8,10 @@ #include "impl/ecmult.h" #include "impl/ecdsa.h" +#ifdef __cplusplus +extern "C" { +#endif + void secp256k1_start(void) { secp256k1_fe_start(); secp256k1_ge_start(); @@ -267,3 +271,7 @@ int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *p secp256k1_num_free(&key); return ret; } + +#ifdef __cplusplus +} +#endif