mirror of https://github.com/bitcoin/bitcoin
parent
852cbee819
commit
a41f32e69d
@ -1,152 +1,7 @@
|
||||
#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
|
||||
|
@ -0,0 +1,156 @@
|
||||
#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
|
@ -0,0 +1,157 @@
|
||||
#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
|
@ -0,0 +1,34 @@
|
||||
#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;
|
||||
}
|
Loading…
Reference in new issue