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);
#ifndef _SECP256K1_NUM_
#define _SECP256K1_NUM_
-#include <assert.h>
-#include <string>
-#include <string.h>
-#include <openssl/bn.h>
-#include <openssl/crypto.h>
-
-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
--- /dev/null
+#ifndef _SECP256K1_NUM_OPENSSL_
+#define _SECP256K1_NUM_OPENSSL_
+
+#include <assert.h>
+#include <string>
+#include <string.h>
+#include <stdlib.h>
+#include <gmp.h>
+
+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
--- /dev/null
+#ifndef _SECP256K1_NUM_OPENSSL_
+#define _SECP256K1_NUM_OPENSSL_
+
+#include <assert.h>
+#include <string>
+#include <string.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+
+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
--- /dev/null
+#include <assert.h>
+
+#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;
+}