From a41f32e69d5bbbfa2483241c5cf54cf8abbe886c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 10 Mar 2013 21:25:19 +0100 Subject: [PATCH] num_gmp.h and begin tests --- group.h | 2 +- num.h | 149 +---------------------------------------------- num_gmp.h | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ num_openssl.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests.cpp | 34 +++++++++++ 5 files changed, 350 insertions(+), 148 deletions(-) create mode 100644 num_gmp.h create mode 100644 num_openssl.h create mode 100644 tests.cpp diff --git a/group.h b/group.h index b9b0837d73..2ae90b3a74 100644 --- a/group.h +++ b/group.h @@ -336,7 +336,7 @@ void GroupElemJac::SetMulLambda(const GroupElemJac &p) { x.SetMult(x, beta); } -void SplitExp(Context &ctx, const Number &exp, Number &exp1, Number exp2) { +void SplitExp(Context &ctx, const Number &exp, Number &exp1, Number &exp2) { const GroupConstants &c = GetGroupConst(); Context ct(ctx); Number bnc1(ct), bnc2(ct), bnt1(ct), bnt2(ct), bnn2(ct); diff --git a/num.h b/num.h index 7910de767b..db1563b963 100644 --- a/num.h +++ b/num.h @@ -1,152 +1,7 @@ #ifndef _SECP256K1_NUM_ #define _SECP256K1_NUM_ -#include -#include -#include -#include -#include - -namespace secp256k1 { - -class Context { -private: - BN_CTX *bn_ctx; - bool root; - bool offspring; - -public: - operator BN_CTX*() { - return bn_ctx; - } - - Context() { - bn_ctx = BN_CTX_new(); - BN_CTX_start(bn_ctx); - root = true; - offspring = false; - } - - Context(Context &par) { - bn_ctx = par.bn_ctx; - root = false; - offspring = false; - par.offspring = true; - BN_CTX_start(bn_ctx); - } - - ~Context() { - BN_CTX_end(bn_ctx); - if (root) - BN_CTX_free(bn_ctx); - } - - BIGNUM *Get() { - assert(offspring == false); - return BN_CTX_get(bn_ctx); - } -}; - - -class Number { -private: - BIGNUM *bn; -public: - Number(Context &ctx) : bn(ctx.Get()) {} - Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) { - SetBytes(bin,len); - } - void SetNumber(const Number &x) { - BN_copy(bn, x.bn); - } - void SetBytes(const unsigned char *bin, int len) { - BN_bin2bn(bin, len, bn); - } - void GetBytes(unsigned char *bin, int len) { - int size = BN_num_bytes(bn); - assert(size <= len); - memset(bin,0,len); - BN_bn2bin(bn, bin + size - len); - } - void SetInt(int x) { - BN_set_word(bn, x); - } - void SetModInverse(Context &ctx, const Number &x, const Number &m) { - BN_mod_inverse(bn, x.bn, m.bn, ctx); - } - void SetModMul(Context &ctx, const Number &a, const Number &b, const Number &m) { - BN_mod_mul(bn, a.bn, b.bn, m.bn, ctx); - } - void SetAdd(Context &ctx, const Number &a1, const Number &a2) { - BN_add(bn, a1.bn, a2.bn); - } - void SetSub(Context &ctx, const Number &a1, const Number &a2) { - BN_sub(bn, a1.bn, a2.bn); - } - void SetMult(Context &ctx, const Number &a1, const Number &a2) { - BN_mul(bn, a1.bn, a2.bn, ctx); - } - void SetDiv(Context &ctx, const Number &a1, const Number &a2) { - BN_div(bn, NULL, a1.bn, a2.bn, ctx); - } - void SetMod(Context &ctx, const Number &a, const Number &m) { - BN_nnmod(bn, m.bn, a.bn, ctx); - } - int Compare(const Number &a) const { - return BN_cmp(bn, a.bn); - } - int GetBits() const { - return BN_num_bits(bn); - } - // return the lowest (rightmost) bits bits, and rshift them away - int ShiftLowBits(Context &ctx, int bits) { - Context ct(ctx); - BIGNUM *tmp = ct.Get(); - BN_copy(tmp, bn); - BN_mask_bits(tmp, bits); - int ret = BN_get_word(tmp); - BN_rshift(bn, bn, bits); - return ret; - } - // check whether number is 0, - bool IsZero() const { - return BN_is_zero(bn); - } - bool IsOdd() const { - return BN_is_odd(bn); - } - bool IsNeg() const { - return BN_is_negative(bn); - } - void Negate() { - BN_set_negative(bn, !IsNeg()); - } - void Shift1() { - BN_rshift1(bn,bn); - } - void Inc() { - BN_add_word(bn,1); - } - void SetHex(const std::string &str) { - BN_hex2bn(&bn, str.c_str()); - } - void SetPseudoRand(const Number &max) { - BN_pseudo_rand_range(bn, max.bn); - } - void SplitInto(Context &ctx, int bits, Number &low, Number &high) const { - BN_copy(low.bn, bn); - BN_mask_bits(low.bn, bits); - BN_rshift(high.bn, bn, bits); - } - - std::string ToString() { - char *str = BN_bn2hex(bn); - std::string ret(str); - OPENSSL_free(str); - return ret; - } -}; - -} +#include "num_gmp.h" +// #include "num_openssl.h" #endif diff --git a/num_gmp.h b/num_gmp.h new file mode 100644 index 0000000000..a71cb7ff44 --- /dev/null +++ b/num_gmp.h @@ -0,0 +1,156 @@ +#ifndef _SECP256K1_NUM_OPENSSL_ +#define _SECP256K1_NUM_OPENSSL_ + +#include +#include +#include +#include +#include + +namespace secp256k1 { + +class Context { +public: + Context() { + } + + Context(Context &par) { + } +}; + +class NumberState { +private: + gmp_randstate_t rng; + +public: + NumberState() { + gmp_randinit_default(rng); + } + + ~NumberState() { + gmp_randclear(rng); + } + + void gen(mpz_t out, mpz_t size) { + mpz_urandomm(out, rng, size); + } +}; + +static NumberState number_state; + +class Number { +private: + mutable mpz_t bn; + Number(const Number &x) { + } +public: + Number(Context &ctx) { + mpz_init(bn); + } + ~Number() { + mpz_clear(bn); + } + Number(Context &ctx, const unsigned char *bin, int len) { + mpz_init(bn); + SetBytes(bin,len); + } + Number &operator=(const Number &x) { + mpz_set(bn, x.bn); + return *this; + } + void SetNumber(const Number &x) { + mpz_set(bn, x.bn); + } + void SetBytes(const unsigned char *bin, int len) { + mpz_import(bn, len, 1, 1, 1, 0, bin); + } + void GetBytes(unsigned char *bin, int len) { + int size = (mpz_sizeinbase(bn,2)+7)/8; + assert(size <= len); + memset(bin,0,len); + mpz_export(bin + size - len, NULL, 1, 1, 1, 0, bn); + } + void SetInt(int x) { + mpz_set_si(bn, x); + } + void SetModInverse(Context &ctx, const Number &x, const Number &m) { + mpz_invert(bn, x.bn, m.bn); + } + void SetModMul(Context &ctx, const Number &a, const Number &b, const Number &m) { + mpz_mul(bn, a.bn, b.bn); + mpz_mod(bn, a.bn, m.bn); + } + void SetAdd(Context &ctx, const Number &a1, const Number &a2) { + mpz_add(bn, a1.bn, a2.bn); + } + void SetSub(Context &ctx, const Number &a1, const Number &a2) { + mpz_sub(bn, a1.bn, a2.bn); + } + void SetMult(Context &ctx, const Number &a1, const Number &a2) { + mpz_mul(bn, a1.bn, a2.bn); + } + void SetDiv(Context &ctx, const Number &a1, const Number &a2) { + mpz_tdiv_q(bn, a1.bn, a2.bn); + } + void SetMod(Context &ctx, const Number &a, const Number &m) { + mpz_mod(bn, a.bn, m.bn); + } + int Compare(const Number &a) const { + return mpz_cmp(bn, a.bn); + } + int GetBits() const { + return mpz_sizeinbase(bn,2); + } + // return the lowest (rightmost) bits bits, and rshift them away + int ShiftLowBits(Context &ctx, int bits) { + int ret = mpz_get_ui(bn) & ((1 << bits) - 1); + mpz_fdiv_q_2exp(bn, bn, bits); + return ret; + } + // check whether number is 0, + bool IsZero() const { + return mpz_size(bn) == 0; + } + bool IsOdd() const { + return mpz_get_ui(bn) & 1; + } + bool IsNeg() const { + return mpz_sgn(bn) < 0; + } + void Negate() { + mpz_neg(bn, bn); + } + void Shift1() { + mpz_fdiv_q_2exp(bn, bn, 1); + } + void Inc() { + mpz_add_ui(bn, bn, 1); + } + void SetHex(const std::string &str) { + mpz_set_str(bn, str.c_str(), 16); + } + void SetPseudoRand(const Number &max) { + number_state.gen(bn, max.bn); + } + void SplitInto(Context &ctx, int bits, Number &low, Number &high) const { + mpz_t tmp; + mpz_init_set_ui(tmp,1); + mpz_mul_2exp(tmp,tmp,bits); + mpz_sub_ui(tmp,tmp,1); + mpz_and(low.bn, bn, tmp); + mpz_clear(tmp); + mpz_fdiv_q_2exp(high.bn, bn, bits); + } + + std::string ToString() { + char *str = (char*)malloc((GetBits() + 7)/8 + 2); + mpz_get_str(str, 16, bn); + std::string ret(str); + free(str); + return ret; + } +}; + +} + +#endif diff --git a/num_openssl.h b/num_openssl.h new file mode 100644 index 0000000000..00dacd8a9d --- /dev/null +++ b/num_openssl.h @@ -0,0 +1,157 @@ +#ifndef _SECP256K1_NUM_OPENSSL_ +#define _SECP256K1_NUM_OPENSSL_ + +#include +#include +#include +#include +#include + +namespace secp256k1 { + +class Context { +private: + BN_CTX *bn_ctx; + bool root; + bool offspring; + +public: + operator BN_CTX*() { + return bn_ctx; + } + + Context() { + bn_ctx = BN_CTX_new(); + BN_CTX_start(bn_ctx); + root = true; + offspring = false; + } + + Context(Context &par) { + bn_ctx = par.bn_ctx; + root = false; + offspring = false; + par.offspring = true; + BN_CTX_start(bn_ctx); + } + + ~Context() { + BN_CTX_end(bn_ctx); + if (root) + BN_CTX_free(bn_ctx); + } + + BIGNUM *Get() { + assert(offspring == false); + return BN_CTX_get(bn_ctx); + } +}; + + +class Number { +private: + BIGNUM *bn; + Number(const Number &x) {} +public: + Number(Context &ctx) : bn(ctx.Get()) {} + Number(Context &ctx, const unsigned char *bin, int len) : bn(ctx.Get()) { + SetBytes(bin,len); + } + void SetNumber(const Number &x) { + BN_copy(bn, x.bn); + } + Number &operator=(const Number &x) { + BN_copy(bn, x.bn); + return *this; + } + void SetBytes(const unsigned char *bin, int len) { + BN_bin2bn(bin, len, bn); + } + void GetBytes(unsigned char *bin, int len) { + int size = BN_num_bytes(bn); + assert(size <= len); + memset(bin,0,len); + BN_bn2bin(bn, bin + size - len); + } + void SetInt(int x) { + BN_set_word(bn, x); + } + void SetModInverse(Context &ctx, const Number &x, const Number &m) { + BN_mod_inverse(bn, x.bn, m.bn, ctx); + } + void SetModMul(Context &ctx, const Number &a, const Number &b, const Number &m) { + BN_mod_mul(bn, a.bn, b.bn, m.bn, ctx); + } + void SetAdd(Context &ctx, const Number &a1, const Number &a2) { + BN_add(bn, a1.bn, a2.bn); + } + void SetSub(Context &ctx, const Number &a1, const Number &a2) { + BN_sub(bn, a1.bn, a2.bn); + } + void SetMult(Context &ctx, const Number &a1, const Number &a2) { + BN_mul(bn, a1.bn, a2.bn, ctx); + } + void SetDiv(Context &ctx, const Number &a1, const Number &a2) { + BN_div(bn, NULL, a1.bn, a2.bn, ctx); + } + void SetMod(Context &ctx, const Number &a, const Number &m) { + BN_nnmod(bn, m.bn, a.bn, ctx); + } + int Compare(const Number &a) const { + return BN_cmp(bn, a.bn); + } + int GetBits() const { + return BN_num_bits(bn); + } + // return the lowest (rightmost) bits bits, and rshift them away + int ShiftLowBits(Context &ctx, int bits) { + Context ct(ctx); + BIGNUM *tmp = ct.Get(); + BN_copy(tmp, bn); + BN_mask_bits(tmp, bits); + int ret = BN_get_word(tmp); + BN_rshift(bn, bn, bits); + return ret; + } + // check whether number is 0, + bool IsZero() const { + return BN_is_zero(bn); + } + bool IsOdd() const { + return BN_is_odd(bn); + } + bool IsNeg() const { + return BN_is_negative(bn); + } + void Negate() { + BN_set_negative(bn, !IsNeg()); + } + void Shift1() { + BN_rshift1(bn,bn); + } + void Inc() { + BN_add_word(bn,1); + } + void SetHex(const std::string &str) { + BN_hex2bn(&bn, str.c_str()); + } + void SetPseudoRand(const Number &max) { + BN_pseudo_rand_range(bn, max.bn); + } + void SplitInto(Context &ctx, int bits, Number &low, Number &high) const { + BN_copy(low.bn, bn); + BN_mask_bits(low.bn, bits); + BN_rshift(high.bn, bn, bits); + } + + std::string ToString() { + char *str = BN_bn2hex(bn); + std::string ret(str); + OPENSSL_free(str); + return ret; + } +}; + +} + +#endif diff --git a/tests.cpp b/tests.cpp new file mode 100644 index 0000000000..5c46b8153a --- /dev/null +++ b/tests.cpp @@ -0,0 +1,34 @@ +#include + +#include "num.h" +#include "field.h" +#include "group.h" +#include "ecmult.h" +#include "ecdsa.h" + +using namespace secp256k1; + +void test_ecmult() { + Context ctx; + FieldElem ax; ax.SetHex("8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004"); + FieldElem ay; ay.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f"); + GroupElemJac a(ax,ay); + Number an(ctx); an.SetHex("84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407"); + Number gn(ctx); gn.SetHex("a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de"); + Number af(ctx); af.SetHex("1337"); + Number gf(ctx); gf.SetHex("7113"); + const Number &order = GetGroupConst().order; + for (int i=0; i<1000; i++) { + ECMult(ctx, a, a, an, gn); + an.SetModMul(ctx, an, af, order); + gn.SetModMul(ctx, gn, gf, order); + } + std::string res = a.ToString(); + assert(res == "(D37F97BBF58B4ECA238329D272C9AF0194F062B851EDF9B40F2294FA00BBFCA2,B127748E9A9F347257051588D44A1B822CA731833B2653AA3646C59A8ADAF295)"); +} + + +int main(void) { + test_ecmult(); + return 0; +}