First step in converting to C: num
This commit is contained in:
parent
21b74c7e5f
commit
4adf6b2a32
6
Makefile
6
Makefile
|
@ -54,8 +54,8 @@ clean-$(CONF):
|
|||
obj/secp256k1-$(CONF).o: $(SECP256K1_FILES)
|
||||
$(CXX) $(FLAGS_COMMON) $(FLAGS_PROD) $(FLAGS_CONF) secp256k1.cpp -c -o obj/secp256k1-$(CONF).o
|
||||
|
||||
bench-$(CONF): obj/secp256k1-$(CONF).o bench.cpp
|
||||
$(CXX) $(FLAGS_COMMON) $(FLAGS_PROD) $(FLAGS_CONF) obj/secp256k1-$(CONF).o bench.cpp $(LIBS) -o bench-$(CONF)
|
||||
bench-$(CONF): $(SECP256K1_FILES) bench.cpp
|
||||
$(CXX) $(FLAGS_COMMON) $(FLAGS_PROD) $(FLAGS_CONF) bench.cpp $(LIBS) -o bench-$(CONF)
|
||||
|
||||
tests-$(CONF): $(SECP256K1_FILES) tests.cpp
|
||||
$(CXX) $(FLAGS_COMMON) $(FLAGS_TEST) $(FLAGS_CONF) tests.cpp $(LIBS) -o tests-$(CONF)
|
||||
$(CXX) $(FLAGS_COMMON) $(FLAGS_DEBUG) $(FLAGS_CONF) tests.cpp $(LIBS) -o tests-$(CONF)
|
||||
|
|
27
bench.cpp
27
bench.cpp
|
@ -1,25 +1,29 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "num.h"
|
||||
#include "field.h"
|
||||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
#include "ecdsa.h"
|
||||
#include "num.cpp"
|
||||
#include "field.cpp"
|
||||
#include "group.cpp"
|
||||
#include "ecmult.cpp"
|
||||
#include "ecdsa.cpp"
|
||||
|
||||
using namespace secp256k1;
|
||||
|
||||
int main() {
|
||||
FieldElem x;
|
||||
const Number &order = GetGroupConst().order;
|
||||
Number r, s, m;
|
||||
const secp256k1_num_t &order = GetGroupConst().order;
|
||||
secp256k1_num_t r, s, m;
|
||||
secp256k1_num_start();
|
||||
secp256k1_num_init(&r);
|
||||
secp256k1_num_init(&s);
|
||||
secp256k1_num_init(&m);
|
||||
Signature sig;
|
||||
x.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||
int cnt = 0;
|
||||
int good = 0;
|
||||
for (int i=0; i<1000000; i++) {
|
||||
r.SetPseudoRand(order);
|
||||
s.SetPseudoRand(order);
|
||||
m.SetPseudoRand(order);
|
||||
secp256k1_num_set_rand(&r, &order);
|
||||
secp256k1_num_set_rand(&s, &order);
|
||||
secp256k1_num_set_rand(&m, &order);
|
||||
sig.SetRS(r,s);
|
||||
GroupElemJac pubkey; pubkey.SetCompressed(x, true);
|
||||
if (pubkey.IsValid()) {
|
||||
|
@ -28,5 +32,8 @@ int main() {
|
|||
}
|
||||
}
|
||||
printf("%i/%i\n", good, cnt);
|
||||
secp256k1_num_free(&r);
|
||||
secp256k1_num_free(&s);
|
||||
secp256k1_num_free(&m);
|
||||
return 0;
|
||||
}
|
||||
|
|
103
ecdsa.cpp
103
ecdsa.cpp
|
@ -35,17 +35,17 @@ bool Signature::Parse(const unsigned char *sig, int size) {
|
|||
if (lenr == 0) return false;
|
||||
if (sig[lenr+4] != 0x02) return false;
|
||||
if (lens == 0) return false;
|
||||
r.SetBytes(sig+4, lenr);
|
||||
s.SetBytes(sig+6+lenr, lens);
|
||||
secp256k1_num_set_bin(&r, sig+4, lenr);
|
||||
secp256k1_num_set_bin(&s, sig+6+lenr, lens);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Signature::Serialize(unsigned char *sig, int *size) {
|
||||
int lenR = (r.GetBits() + 7)/8;
|
||||
if (lenR == 0 || r.CheckBit(lenR*8-1))
|
||||
int lenR = (secp256k1_num_bits(&r) + 7)/8;
|
||||
if (lenR == 0 || secp256k1_num_get_bit(&r, lenR*8-1))
|
||||
lenR++;
|
||||
int lenS = (s.GetBits() + 7)/8;
|
||||
if (lenS == 0 || s.CheckBit(lenS*8-1))
|
||||
int lenS = (secp256k1_num_bits(&s) + 7)/8;
|
||||
if (lenS == 0 || secp256k1_num_get_bit(&s, lenS*8-1))
|
||||
lenS++;
|
||||
if (*size < 6+lenS+lenR)
|
||||
return false;
|
||||
|
@ -54,45 +54,56 @@ bool Signature::Serialize(unsigned char *sig, int *size) {
|
|||
sig[1] = 4 + lenS + lenR;
|
||||
sig[2] = 0x02;
|
||||
sig[3] = lenR;
|
||||
r.GetBytes(sig+4, lenR);
|
||||
secp256k1_num_get_bin(sig+4, lenR, &r);
|
||||
sig[4+lenR] = 0x02;
|
||||
sig[5+lenR] = lenS;
|
||||
s.GetBytes(sig+6, lenS);
|
||||
secp256k1_num_get_bin(sig+lenR+6, lenS, &s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Signature::RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) const {
|
||||
bool Signature::RecomputeR(secp256k1_num_t &r2, const GroupElemJac &pubkey, const secp256k1_num_t &message) const {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
|
||||
if (r.IsNeg() || s.IsNeg())
|
||||
if (secp256k1_num_is_neg(&r) || secp256k1_num_is_neg(&s))
|
||||
return false;
|
||||
if (r.IsZero() || s.IsZero())
|
||||
if (secp256k1_num_is_zero(&r) || secp256k1_num_is_zero(&s))
|
||||
return false;
|
||||
if (r.Compare(c.order) >= 0 || s.Compare(c.order) >= 0)
|
||||
if (secp256k1_num_cmp(&r, &c.order) >= 0 || secp256k1_num_cmp(&s, &c.order) >= 0)
|
||||
return false;
|
||||
|
||||
Number sn, u1, u2;
|
||||
sn.SetModInverse(s, c.order);
|
||||
u1.SetModMul(sn, message, c.order);
|
||||
u2.SetModMul(sn, r, c.order);
|
||||
bool ret = false;
|
||||
secp256k1_num_t sn, u1, u2;
|
||||
secp256k1_num_init(&sn);
|
||||
secp256k1_num_init(&u1);
|
||||
secp256k1_num_init(&u2);
|
||||
secp256k1_num_mod_inverse(&sn, &s, &c.order);
|
||||
secp256k1_num_mod_mul(&u1, &sn, &message, &c.order);
|
||||
secp256k1_num_mod_mul(&u2, &sn, &r, &c.order);
|
||||
GroupElemJac pr; ECMult(pr, pubkey, u2, u1);
|
||||
if (pr.IsInfinity())
|
||||
return false;
|
||||
FieldElem xr; pr.GetX(xr);
|
||||
xr.Normalize();
|
||||
unsigned char xrb[32]; xr.GetBytes(xrb);
|
||||
r2.SetBytes(xrb,32); r2.SetMod(r2,c.order);
|
||||
return true;
|
||||
if (!pr.IsInfinity()) {
|
||||
FieldElem xr; pr.GetX(xr);
|
||||
xr.Normalize();
|
||||
unsigned char xrb[32]; xr.GetBytes(xrb);
|
||||
secp256k1_num_set_bin(&r2, xrb, 32);
|
||||
secp256k1_num_mod(&r2, &r2, &c.order);
|
||||
ret = true;
|
||||
}
|
||||
secp256k1_num_free(&sn);
|
||||
secp256k1_num_free(&u1);
|
||||
secp256k1_num_free(&u2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Signature::Verify(const GroupElemJac &pubkey, const Number &message) const {
|
||||
Number r2;
|
||||
if (!RecomputeR(r2, pubkey, message))
|
||||
return false;
|
||||
return r2.Compare(r) == 0;
|
||||
bool Signature::Verify(const GroupElemJac &pubkey, const secp256k1_num_t &message) const {
|
||||
secp256k1_num_t r2;
|
||||
secp256k1_num_init(&r2);
|
||||
bool ret = false;
|
||||
ret = RecomputeR(r2, pubkey, message) && secp256k1_num_cmp(&r, &r2) == 0;
|
||||
secp256k1_num_free(&r2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Signature::Sign(const Number &seckey, const Number &message, const Number &nonce) {
|
||||
bool Signature::Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &message, const secp256k1_num_t &nonce) {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
|
||||
GroupElemJac rp;
|
||||
|
@ -102,27 +113,33 @@ bool Signature::Sign(const Number &seckey, const Number &message, const Number &
|
|||
unsigned char b[32];
|
||||
rx.Normalize();
|
||||
rx.GetBytes(b);
|
||||
r.SetBytes(b, 32);
|
||||
r.SetMod(r, c.order);
|
||||
Number n;
|
||||
n.SetModMul(r, seckey, c.order);
|
||||
n.SetAdd(message, n);
|
||||
s.SetModInverse(nonce, c.order);
|
||||
s.SetModMul(s, n, c.order);
|
||||
if (s.IsZero())
|
||||
secp256k1_num_set_bin(&r, b, 32);
|
||||
secp256k1_num_mod(&r, &r, &c.order);
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_mod_mul(&n, &r, &seckey, &c.order);
|
||||
secp256k1_num_add(&n, &n, &message);
|
||||
secp256k1_num_mod_inverse(&s, &nonce, &c.order);
|
||||
secp256k1_num_mod_mul(&s, &s, &n, &c.order);
|
||||
secp256k1_num_free(&n);
|
||||
if (secp256k1_num_is_zero(&s))
|
||||
return false;
|
||||
if (s.IsOdd())
|
||||
s.SetSub(c.order, s);
|
||||
if (secp256k1_num_is_odd(&s))
|
||||
secp256k1_num_sub(&s, &c.order, &s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Signature::SetRS(const Number &rin, const Number &sin) {
|
||||
r = rin;
|
||||
s = sin;
|
||||
void Signature::SetRS(const secp256k1_num_t &rin, const secp256k1_num_t &sin) {
|
||||
secp256k1_num_copy(&r, &rin);
|
||||
secp256k1_num_copy(&s, &sin);
|
||||
}
|
||||
|
||||
std::string Signature::ToString() const {
|
||||
return "(" + r.ToString() + "," + s.ToString() + ")";
|
||||
char rs[65], ss[65];
|
||||
int rl = 65, sl = 65;
|
||||
secp256k1_num_get_hex(rs, &rl, &r);
|
||||
secp256k1_num_get_hex(ss, &sl, &s);
|
||||
return "(" + std::string(rs) + "," + std::string(ss) + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
19
ecdsa.h
19
ecdsa.h
|
@ -5,15 +5,24 @@ namespace secp256k1 {
|
|||
|
||||
class Signature {
|
||||
private:
|
||||
Number r,s;
|
||||
secp256k1_num_t r,s;
|
||||
|
||||
public:
|
||||
Signature() {
|
||||
secp256k1_num_init(&r);
|
||||
secp256k1_num_init(&s);
|
||||
}
|
||||
~Signature() {
|
||||
secp256k1_num_free(&r);
|
||||
secp256k1_num_free(&s);
|
||||
}
|
||||
|
||||
bool Parse(const unsigned char *sig, int size);
|
||||
bool Serialize(unsigned char *sig, int *size);
|
||||
bool RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) const;
|
||||
bool Verify(const GroupElemJac &pubkey, const Number &message) const;
|
||||
bool Sign(const Number &seckey, const Number &message, const Number &nonce);
|
||||
void SetRS(const Number &rin, const Number &sin);
|
||||
bool RecomputeR(secp256k1_num_t &r2, const GroupElemJac &pubkey, const secp256k1_num_t &message) const;
|
||||
bool Verify(const GroupElemJac &pubkey, const secp256k1_num_t &message) const;
|
||||
bool Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &message, const secp256k1_num_t &nonce);
|
||||
void SetRS(const secp256k1_num_t &rin, const secp256k1_num_t &sin);
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
|
|
51
ecmult.cpp
51
ecmult.cpp
|
@ -61,29 +61,31 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
WNAF(const Number &exp, int w) : used(0) {
|
||||
WNAF(const secp256k1_num_t &exp, int w) : used(0) {
|
||||
int zeroes = 0;
|
||||
Number x;
|
||||
x.SetNumber(exp);
|
||||
secp256k1_num_t x;
|
||||
secp256k1_num_init(&x);
|
||||
secp256k1_num_copy(&x, &exp);
|
||||
int sign = 1;
|
||||
if (x.IsNeg()) {
|
||||
if (secp256k1_num_is_neg(&x)) {
|
||||
sign = -1;
|
||||
x.Negate();
|
||||
secp256k1_num_negate(&x);
|
||||
}
|
||||
while (!x.IsZero()) {
|
||||
while (!x.IsOdd()) {
|
||||
while (!secp256k1_num_is_zero(&x)) {
|
||||
while (!secp256k1_num_is_odd(&x)) {
|
||||
zeroes++;
|
||||
x.Shift1();
|
||||
secp256k1_num_shift(&x, 1);
|
||||
}
|
||||
int word = x.ShiftLowBits(w);
|
||||
int word = secp256k1_num_shift(&x, w);
|
||||
if (word & (1 << (w-1))) {
|
||||
x.Inc();
|
||||
secp256k1_num_inc(&x);
|
||||
PushNAF(sign * (word - (1 << w)), zeroes);
|
||||
} else {
|
||||
PushNAF(sign * word, zeroes);
|
||||
}
|
||||
zeroes = w-1;
|
||||
}
|
||||
secp256k1_num_free(&x);
|
||||
}
|
||||
|
||||
int GetSize() const {
|
||||
|
@ -145,19 +147,27 @@ const ECMultConsts &GetECMultConsts() {
|
|||
return ecmult_consts;
|
||||
}
|
||||
|
||||
void ECMultBase(GroupElemJac &out, const Number &gn) {
|
||||
Number n; n.SetNumber(gn);
|
||||
void ECMultBase(GroupElemJac &out, const secp256k1_num_t &gn) {
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_copy(&n, &gn);
|
||||
const ECMultConsts &c = GetECMultConsts();
|
||||
out.SetAffine(c.prec[0][n.ShiftLowBits(4)]);
|
||||
out.SetAffine(c.prec[0][secp256k1_num_shift(&n, 4)]);
|
||||
for (int j=1; j<64; j++) {
|
||||
out.SetAdd(out, c.prec[j][n.ShiftLowBits(4)]);
|
||||
out.SetAdd(out, c.prec[j][secp256k1_num_shift(&n, 4)]);
|
||||
}
|
||||
secp256k1_num_free(&n);
|
||||
out.SetAdd(out, c.fin);
|
||||
}
|
||||
|
||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn) {
|
||||
Number an1, an2;
|
||||
Number gn1, gn2;
|
||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const secp256k1_num_t &an, const secp256k1_num_t &gn) {
|
||||
secp256k1_num_t an1, an2;
|
||||
secp256k1_num_t gn1, gn2;
|
||||
|
||||
secp256k1_num_init(&an1);
|
||||
secp256k1_num_init(&an2);
|
||||
secp256k1_num_init(&gn1);
|
||||
secp256k1_num_init(&gn2);
|
||||
|
||||
SplitExp(an, an1, an2);
|
||||
// printf("an=%s\n", an.ToString().c_str());
|
||||
|
@ -165,7 +175,7 @@ void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Nu
|
|||
// printf("an2=%s\n", an2.ToString().c_str());
|
||||
// printf("an1.len=%i\n", an1.GetBits());
|
||||
// printf("an2.len=%i\n", an2.GetBits());
|
||||
gn.SplitInto(128, gn1, gn2);
|
||||
secp256k1_num_split(&gn1, &gn2, &gn, 128);
|
||||
|
||||
WNAF<128> wa1(an1, WINDOW_A);
|
||||
WNAF<128> wa2(an2, WINDOW_A);
|
||||
|
@ -206,6 +216,11 @@ void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Nu
|
|||
out.SetAdd(out, tmpa);
|
||||
}
|
||||
}
|
||||
|
||||
secp256k1_num_free(&an1);
|
||||
secp256k1_num_free(&an2);
|
||||
secp256k1_num_free(&gn1);
|
||||
secp256k1_num_free(&gn2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
4
ecmult.h
4
ecmult.h
|
@ -6,8 +6,8 @@
|
|||
|
||||
namespace secp256k1 {
|
||||
|
||||
void ECMultBase(GroupElemJac &out, const Number &gn);
|
||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const Number &an, const Number &gn);
|
||||
void ECMultBase(GroupElemJac &out, const secp256k1_num_t &gn);
|
||||
void ECMult(GroupElemJac &out, const GroupElemJac &a, const secp256k1_num_t &an, const secp256k1_num_t &gn);
|
||||
|
||||
}
|
||||
|
||||
|
|
20
field.cpp
20
field.cpp
|
@ -363,7 +363,14 @@ static const unsigned char field_p_[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
|||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F};
|
||||
|
||||
FieldConstants::FieldConstants() : field_p(field_p_, sizeof(field_p_)) {}
|
||||
FieldConstants::FieldConstants() {
|
||||
secp256k1_num_init(&field_p);
|
||||
secp256k1_num_set_bin(&field_p, field_p_, sizeof(field_p_));
|
||||
}
|
||||
|
||||
FieldConstants::~FieldConstants() {
|
||||
secp256k1_num_free(&field_p);
|
||||
}
|
||||
|
||||
const FieldConstants &GetFieldConst() {
|
||||
static const FieldConstants field_const;
|
||||
|
@ -408,10 +415,13 @@ void FieldElem::SetInverse(FieldElem &a) {
|
|||
a.Normalize();
|
||||
a.GetBytes(b);
|
||||
{
|
||||
const Number &p = GetFieldConst().field_p;
|
||||
Number n; n.SetBytes(b, 32);
|
||||
n.SetModInverse(n, p);
|
||||
n.GetBytes(b, 32);
|
||||
const secp256k1_num_t &p = GetFieldConst().field_p;
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_set_bin(&n, b, 32);
|
||||
secp256k1_num_mod_inverse(&n, &n, &p);
|
||||
secp256k1_num_get_bin(b, 32, &n);
|
||||
secp256k1_num_free(&n);
|
||||
}
|
||||
SetBytes(b);
|
||||
#endif
|
||||
|
|
3
field.h
3
field.h
|
@ -77,9 +77,10 @@ public:
|
|||
|
||||
class FieldConstants {
|
||||
public:
|
||||
const Number field_p;
|
||||
secp256k1_num_t field_p;
|
||||
|
||||
FieldConstants();
|
||||
~FieldConstants();
|
||||
};
|
||||
|
||||
const FieldConstants &GetFieldConst();
|
||||
|
|
74
group.cpp
74
group.cpp
|
@ -291,13 +291,28 @@ static const unsigned char a2_[] = {0x01,
|
|||
0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8};
|
||||
|
||||
GroupConstants::GroupConstants() : g_x(g_x_), g_y(g_y_),
|
||||
order(order_, sizeof(order_)),
|
||||
g(g_x,g_y),
|
||||
beta(beta_),
|
||||
lambda(lambda_, sizeof(lambda_)),
|
||||
a1b2(a1b2_, sizeof(a1b2_)),
|
||||
b1(b1_, sizeof(b1_)),
|
||||
a2(a2_, sizeof(a2_)) {}
|
||||
beta(beta_) {
|
||||
secp256k1_num_init(&order);
|
||||
secp256k1_num_init(&lambda);
|
||||
secp256k1_num_init(&a1b2);
|
||||
secp256k1_num_init(&b1);
|
||||
secp256k1_num_init(&a2);
|
||||
|
||||
secp256k1_num_set_bin(&order, order_, sizeof(order_));
|
||||
secp256k1_num_set_bin(&lambda, lambda_, sizeof(lambda_));
|
||||
secp256k1_num_set_bin(&a1b2, a1b2_, sizeof(a1b2_));
|
||||
secp256k1_num_set_bin(&b1, b1_, sizeof(b1_));
|
||||
secp256k1_num_set_bin(&a2, a2_, sizeof(a2_));
|
||||
}
|
||||
|
||||
GroupConstants::~GroupConstants() {
|
||||
secp256k1_num_free(&order);
|
||||
secp256k1_num_free(&lambda);
|
||||
secp256k1_num_free(&a1b2);
|
||||
secp256k1_num_free(&b1);
|
||||
secp256k1_num_free(&a2);
|
||||
}
|
||||
|
||||
const GroupConstants &GetGroupConst() {
|
||||
static const GroupConstants group_const;
|
||||
|
@ -310,27 +325,40 @@ void GroupElemJac::SetMulLambda(const GroupElemJac &p) {
|
|||
x.SetMult(x, beta);
|
||||
}
|
||||
|
||||
void SplitExp(const Number &exp, Number &exp1, Number &exp2) {
|
||||
void SplitExp(const secp256k1_num_t &exp, secp256k1_num_t &exp1, secp256k1_num_t &exp2) {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
Number bnc1, bnc2, bnt1, bnt2, bnn2;
|
||||
bnn2.SetNumber(c.order);
|
||||
bnn2.Shift1();
|
||||
secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;
|
||||
|
||||
bnc1.SetMult(exp, c.a1b2);
|
||||
bnc1.SetAdd(bnc1, bnn2);
|
||||
bnc1.SetDiv(bnc1, c.order);
|
||||
secp256k1_num_init(&bnc1);
|
||||
secp256k1_num_init(&bnc2);
|
||||
secp256k1_num_init(&bnt1);
|
||||
secp256k1_num_init(&bnt2);
|
||||
secp256k1_num_init(&bnn2);
|
||||
|
||||
bnc2.SetMult(exp, c.b1);
|
||||
bnc2.SetAdd(bnc2, bnn2);
|
||||
bnc2.SetDiv(bnc2, c.order);
|
||||
secp256k1_num_copy(&bnn2, &c.order);
|
||||
secp256k1_num_shift(&bnn2, 1);
|
||||
|
||||
bnt1.SetMult(bnc1, c.a1b2);
|
||||
bnt2.SetMult(bnc2, c.a2);
|
||||
bnt1.SetAdd(bnt1, bnt2);
|
||||
exp1.SetSub(exp, bnt1);
|
||||
bnt1.SetMult(bnc1, c.b1);
|
||||
bnt2.SetMult(bnc2, c.a1b2);
|
||||
exp2.SetSub(bnt1, bnt2);
|
||||
secp256k1_num_mul(&bnc1, &exp, &c.a1b2);
|
||||
secp256k1_num_add(&bnc1, &bnc1, &bnn2);
|
||||
secp256k1_num_div(&bnc1, &bnc1, &c.order);
|
||||
|
||||
secp256k1_num_mul(&bnc2, &exp, &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(&exp1, &exp, &bnt1);
|
||||
secp256k1_num_mul(&bnt1, &bnc1, &c.b1);
|
||||
secp256k1_num_mul(&bnt2, &bnc2, &c.a1b2);
|
||||
secp256k1_num_sub(&exp2, &bnt1, &bnt2);
|
||||
|
||||
secp256k1_num_free(&bnc1);
|
||||
secp256k1_num_free(&bnc2);
|
||||
secp256k1_num_free(&bnt1);
|
||||
secp256k1_num_free(&bnt2);
|
||||
secp256k1_num_free(&bnn2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
7
group.h
7
group.h
|
@ -95,17 +95,18 @@ private:
|
|||
const FieldElem g_y;
|
||||
|
||||
public:
|
||||
const Number order;
|
||||
secp256k1_num_t order;
|
||||
const GroupElem g;
|
||||
const FieldElem beta;
|
||||
const Number lambda, a1b2, b1, a2;
|
||||
secp256k1_num_t lambda, a1b2, b1, a2;
|
||||
|
||||
GroupConstants();
|
||||
~GroupConstants();
|
||||
};
|
||||
|
||||
const GroupConstants &GetGroupConst();
|
||||
|
||||
void SplitExp(const Number &exp, Number &exp1, Number &exp2);
|
||||
void SplitExp(const secp256k1_num_t &exp, secp256k1_num_t &exp1, secp256k1_num_t &exp2);
|
||||
|
||||
}
|
||||
|
||||
|
|
28
num.h
28
num.h
|
@ -9,4 +9,32 @@
|
|||
#error "Please select num implementation"
|
||||
#endif
|
||||
|
||||
void static secp256k1_num_start(void);
|
||||
void static secp256k1_num_init(secp256k1_num_t *r);
|
||||
void static secp256k1_num_free(secp256k1_num_t *r);
|
||||
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a);
|
||||
void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a);
|
||||
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen);
|
||||
void static secp256k1_num_set_int(secp256k1_num_t *r, int a);
|
||||
void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m);
|
||||
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);
|
||||
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
|
||||
int static secp256k1_num_bits(const secp256k1_num_t *a);
|
||||
int static secp256k1_num_shift(secp256k1_num_t *r, int bits);
|
||||
int static secp256k1_num_is_zero(const secp256k1_num_t *a);
|
||||
int static secp256k1_num_is_odd(const secp256k1_num_t *a);
|
||||
int static secp256k1_num_is_neg(const secp256k1_num_t *a);
|
||||
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos);
|
||||
void static secp256k1_num_inc(secp256k1_num_t *r);
|
||||
void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen);
|
||||
void static secp256k1_num_get_hex(char *r, int *rlen, const secp256k1_num_t *a);
|
||||
void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits);
|
||||
void static secp256k1_num_negate(secp256k1_num_t *r);
|
||||
void static secp256k1_num_set_rand(secp256k1_num_t *r, const secp256k1_num_t *a);
|
||||
|
||||
#endif
|
||||
|
|
185
num_gmp.cpp
185
num_gmp.cpp
|
@ -1,171 +1,148 @@
|
|||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmp.h>
|
||||
|
||||
#include "num_gmp.h"
|
||||
#include "num.h"
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
class NumberState {
|
||||
private:
|
||||
typedef struct {
|
||||
int initialized;
|
||||
gmp_randstate_t rng;
|
||||
} secp256k1_num_state_t;
|
||||
|
||||
public:
|
||||
NumberState() {
|
||||
gmp_randinit_default(rng);
|
||||
}
|
||||
static secp256k1_num_state_t secp256k1_num_state = {};
|
||||
|
||||
~NumberState() {
|
||||
gmp_randclear(rng);
|
||||
}
|
||||
|
||||
void gen(mpz_t out, mpz_t size) {
|
||||
mpz_urandomm(out, rng, size);
|
||||
}
|
||||
};
|
||||
|
||||
static NumberState number_state;
|
||||
|
||||
Number::Number(const Number &x) {
|
||||
mpz_init_set(bn, x.bn);
|
||||
void static secp256k1_num_start(void) {
|
||||
if (secp256k1_num_state.initialized)
|
||||
return;
|
||||
secp256k1_num_state.initialized = 1;
|
||||
gmp_randinit_default(secp256k1_num_state.rng);
|
||||
}
|
||||
|
||||
Number::Number() {
|
||||
mpz_init(bn);
|
||||
void static secp256k1_num_init(secp256k1_num_t *r) {
|
||||
mpz_init(r->bn);
|
||||
}
|
||||
|
||||
Number::~Number() {
|
||||
mpz_clear(bn);
|
||||
void static secp256k1_num_free(secp256k1_num_t *r) {
|
||||
mpz_clear(r->bn);
|
||||
}
|
||||
|
||||
Number &Number::operator=(const Number &x) {
|
||||
mpz_set(bn, x.bn);
|
||||
return *this;
|
||||
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
||||
mpz_set(r->bn, a->bn);
|
||||
}
|
||||
|
||||
void Number::SetNumber(const Number &x) {
|
||||
mpz_set(bn, x.bn);
|
||||
}
|
||||
|
||||
Number::Number(const unsigned char *bin, int len) {
|
||||
mpz_init(bn);
|
||||
SetBytes(bin,len);
|
||||
}
|
||||
|
||||
void Number::SetBytes(const unsigned char *bin, unsigned int len) {
|
||||
mpz_import(bn, len, 1, 1, 1, 0, bin);
|
||||
}
|
||||
|
||||
bool Number::CheckBit(int pos) const {
|
||||
return mpz_tstbit(bn, pos);
|
||||
}
|
||||
|
||||
void Number::GetBytes(unsigned char *bin, unsigned int len) {
|
||||
unsigned int size = (mpz_sizeinbase(bn,2)+7)/8;
|
||||
assert(size <= len);
|
||||
memset(bin,0,len);
|
||||
void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
|
||||
unsigned int size = (mpz_sizeinbase(a->bn,2)+7)/8;
|
||||
assert(size <= rlen);
|
||||
memset(r,0,rlen);
|
||||
size_t count = 0;
|
||||
mpz_export(bin + len - size, &count, 1, 1, 1, 0, bn);
|
||||
mpz_export(r + rlen - size, &count, 1, 1, 1, 0, a->bn);
|
||||
assert(count == 0 || size == count);
|
||||
}
|
||||
|
||||
void Number::SetInt(int x) {
|
||||
mpz_set_si(bn, x);
|
||||
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
|
||||
mpz_import(r->bn, alen, 1, 1, 1, 0, a);
|
||||
}
|
||||
|
||||
void Number::SetModInverse(const Number &x, const Number &m) {
|
||||
mpz_invert(bn, x.bn, m.bn);
|
||||
void static secp256k1_num_set_int(secp256k1_num_t *r, int a) {
|
||||
mpz_set_si(r->bn, a);
|
||||
}
|
||||
|
||||
void Number::SetModMul(const Number &a, const Number &b, const Number &m) {
|
||||
mpz_mul(bn, a.bn, b.bn);
|
||||
mpz_mod(bn, bn, m.bn);
|
||||
void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
|
||||
mpz_invert(r->bn, a->bn, m->bn);
|
||||
}
|
||||
|
||||
void Number::SetAdd(const Number &a1, const Number &a2) {
|
||||
mpz_add(bn, a1.bn, a2.bn);
|
||||
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) {
|
||||
mpz_mul(r->bn, a->bn, b->bn);
|
||||
mpz_mod(r->bn, r->bn, m->bn);
|
||||
}
|
||||
|
||||
void Number::SetSub(const Number &a1, const Number &a2) {
|
||||
mpz_sub(bn, a1.bn, a2.bn);
|
||||
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
return mpz_cmp(a->bn, b->bn);
|
||||
}
|
||||
|
||||
void Number::SetMult(const Number &a1, const Number &a2) {
|
||||
mpz_mul(bn, a1.bn, a2.bn);
|
||||
void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
mpz_add(r->bn, a->bn, b->bn);
|
||||
}
|
||||
|
||||
void Number::SetDiv(const Number &a1, const Number &a2) {
|
||||
mpz_tdiv_q(bn, a1.bn, a2.bn);
|
||||
void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
mpz_sub(r->bn, a->bn, b->bn);
|
||||
}
|
||||
|
||||
void Number::SetMod(const Number &a, const Number &m) {
|
||||
mpz_mod(bn, a.bn, m.bn);
|
||||
void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
mpz_mul(r->bn, a->bn, b->bn);
|
||||
}
|
||||
|
||||
int Number::Compare(const Number &a) const {
|
||||
return mpz_cmp(bn, a.bn);
|
||||
void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
mpz_tdiv_q(r->bn, a->bn, b->bn);
|
||||
}
|
||||
|
||||
int Number::GetBits() const {
|
||||
return mpz_sizeinbase(bn,2);
|
||||
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
mpz_mod(r->bn, a->bn, b->bn);
|
||||
}
|
||||
|
||||
int Number::ShiftLowBits(int bits) {
|
||||
int ret = mpz_get_ui(bn) & ((1 << bits) - 1);
|
||||
mpz_fdiv_q_2exp(bn, bn, bits);
|
||||
int static secp256k1_num_bits(const secp256k1_num_t *a) {
|
||||
return mpz_sizeinbase(a->bn,2);
|
||||
}
|
||||
|
||||
int static secp256k1_num_shift(secp256k1_num_t *r, int bits) {
|
||||
int ret = mpz_get_ui(r->bn) & ((1 << bits) - 1);
|
||||
mpz_fdiv_q_2exp(r->bn, r->bn, bits);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Number::IsZero() const {
|
||||
return mpz_size(bn) == 0;
|
||||
int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
|
||||
return mpz_size(a->bn) == 0;
|
||||
}
|
||||
|
||||
bool Number::IsOdd() const {
|
||||
return mpz_get_ui(bn) & 1;
|
||||
int static secp256k1_num_is_odd(const secp256k1_num_t *a) {
|
||||
return mpz_get_ui(a->bn) & 1;
|
||||
}
|
||||
|
||||
bool Number::IsNeg() const {
|
||||
return mpz_sgn(bn) < 0;
|
||||
int static secp256k1_num_is_neg(const secp256k1_num_t *a) {
|
||||
return mpz_sgn(a->bn) < 0;
|
||||
}
|
||||
|
||||
void Number::Negate() {
|
||||
mpz_neg(bn, bn);
|
||||
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
|
||||
return mpz_tstbit(a->bn, pos);
|
||||
}
|
||||
|
||||
void Number::Shift1() {
|
||||
mpz_fdiv_q_2exp(bn, bn, 1);
|
||||
void static secp256k1_num_inc(secp256k1_num_t *r) {
|
||||
mpz_add_ui(r->bn, r->bn, 1);
|
||||
}
|
||||
|
||||
void Number::Inc() {
|
||||
mpz_add_ui(bn, 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;
|
||||
mpz_set_str(r->bn, str, 16);
|
||||
free(str);
|
||||
}
|
||||
|
||||
void Number::SetHex(const std::string &str) {
|
||||
mpz_set_str(bn, str.c_str(), 16);
|
||||
void static secp256k1_num_get_hex(char *r, int *rlen, const secp256k1_num_t *a) {
|
||||
int len = mpz_sizeinbase(a->bn, 16) + 2;
|
||||
if (*rlen < len) {
|
||||
*rlen = len;
|
||||
return;
|
||||
}
|
||||
mpz_get_str(r, 16, a->bn);
|
||||
*rlen = len;
|
||||
}
|
||||
|
||||
void Number::SetPseudoRand(const Number &max) {
|
||||
number_state.gen(bn, max.bn);
|
||||
}
|
||||
|
||||
void Number::SplitInto(int bits, Number &low, Number &high) const {
|
||||
void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
|
||||
mpz_t tmp;
|
||||
mpz_init_set_ui(tmp,1);
|
||||
mpz_mul_2exp(tmp,tmp,bits);
|
||||
mpz_mul_2exp(tmp, tmp, bits);
|
||||
mpz_sub_ui(tmp,tmp,1);
|
||||
mpz_and(low.bn, bn, tmp);
|
||||
mpz_and(rl->bn, a->bn, tmp);
|
||||
mpz_clear(tmp);
|
||||
mpz_fdiv_q_2exp(high.bn, bn, bits);
|
||||
mpz_fdiv_q_2exp(rh->bn, a->bn, bits);
|
||||
}
|
||||
|
||||
std::string Number::ToString() const {
|
||||
char *str = (char*)malloc(mpz_sizeinbase(bn,16) + 2);
|
||||
mpz_get_str(str, 16, bn);
|
||||
std::string ret(str);
|
||||
free(str);
|
||||
return ret;
|
||||
void static secp256k1_num_negate(secp256k1_num_t *r) {
|
||||
mpz_neg(r->bn, r->bn);
|
||||
}
|
||||
|
||||
void static secp256k1_num_set_rand(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
||||
mpz_urandomm(r->bn, secp256k1_num_state.rng, a->bn);
|
||||
}
|
||||
|
|
44
num_gmp.h
44
num_gmp.h
|
@ -1,48 +1,10 @@
|
|||
#ifndef _SECP256K1_NUM_GMP_
|
||||
#define _SECP256K1_NUM_GMP_
|
||||
|
||||
#include <string>
|
||||
#include <gmp.h>
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
class Number {
|
||||
private:
|
||||
mutable mpz_t bn;
|
||||
Number(const Number &x);
|
||||
|
||||
public:
|
||||
Number();
|
||||
~Number();
|
||||
Number(const unsigned char *bin, int len);
|
||||
Number &operator=(const Number &x);
|
||||
void SetNumber(const Number &x);
|
||||
void SetBytes(const unsigned char *bin, unsigned int len);
|
||||
void GetBytes(unsigned char *bin, unsigned int len);
|
||||
void SetInt(int x);
|
||||
void SetModInverse(const Number &x, const Number &m);
|
||||
void SetModMul(const Number &a, const Number &b, const Number &m);
|
||||
void SetAdd(const Number &a1, const Number &a2);
|
||||
void SetSub(const Number &a1, const Number &a2);
|
||||
void SetMult(const Number &a1, const Number &a2);
|
||||
void SetDiv(const Number &a1, const Number &a2);
|
||||
void SetMod(const Number &a, const Number &m);
|
||||
int Compare(const Number &a) const;
|
||||
int GetBits() const;
|
||||
int ShiftLowBits(int bits);
|
||||
bool IsZero() const;
|
||||
bool IsOdd() const;
|
||||
bool IsNeg() const;
|
||||
bool CheckBit(int pos) const;
|
||||
void Negate();
|
||||
void Shift1();
|
||||
void Inc();
|
||||
void SetHex(const std::string &str);
|
||||
void SetPseudoRand(const Number &max);
|
||||
void SplitInto(int bits, Number &low, Number &high) const;
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
}
|
||||
typedef struct {
|
||||
mpz_t bn;
|
||||
} secp256k1_num_t;
|
||||
|
||||
#endif
|
||||
|
|
215
num_openssl.cpp
215
num_openssl.cpp
|
@ -1,183 +1,146 @@
|
|||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "num_openssl.h"
|
||||
#include "num.h"
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
class Context {
|
||||
private:
|
||||
BN_CTX *ctx;
|
||||
|
||||
operator BN_CTX*() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
friend class Number;
|
||||
public:
|
||||
Context() {
|
||||
ctx = BN_CTX_new();
|
||||
}
|
||||
|
||||
~Context() {
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
};
|
||||
|
||||
Number::operator const BIGNUM*() const {
|
||||
return &b;
|
||||
void static secp256k1_num_start() {
|
||||
}
|
||||
|
||||
Number::operator BIGNUM*() {
|
||||
return &b;
|
||||
void static secp256k1_num_init(secp256k1_num_t *r) {
|
||||
BN_init(&r->bn);
|
||||
}
|
||||
|
||||
Number::Number() {
|
||||
BN_init(*this);
|
||||
void static secp256k1_num_free(secp256k1_num_t *r) {
|
||||
BN_free(&r->bn);
|
||||
}
|
||||
|
||||
Number::~Number() {
|
||||
BN_free(*this);
|
||||
void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
||||
BN_copy(&r->bn, &a->bn);
|
||||
}
|
||||
|
||||
Number::Number(const unsigned char *bin, int len) {
|
||||
BN_init(*this);
|
||||
SetBytes(bin,len);
|
||||
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 Number::SetNumber(const Number &x) {
|
||||
BN_copy(*this, x);
|
||||
void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
|
||||
BN_bin2bn(a, alen, &r->bn);
|
||||
}
|
||||
|
||||
Number::Number(const Number &x) {
|
||||
BN_init(*this);
|
||||
BN_copy(*this, x);
|
||||
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);
|
||||
}
|
||||
|
||||
Number &Number::operator=(const Number &x) {
|
||||
BN_copy(*this, x);
|
||||
return *this;
|
||||
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 Number::SetBytes(const unsigned char *bin, int len) {
|
||||
BN_bin2bn(bin, len, *this);
|
||||
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);
|
||||
}
|
||||
|
||||
void Number::GetBytes(unsigned char *bin, int len) {
|
||||
int size = BN_num_bytes(*this);
|
||||
assert(size <= len);
|
||||
memset(bin,0,len);
|
||||
BN_bn2bin(*this, bin + len - size);
|
||||
int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
return BN_cmp(&a->bn, &b->bn);
|
||||
}
|
||||
|
||||
void Number::SetInt(int x) {
|
||||
if (x >= 0) {
|
||||
BN_set_word(*this, x);
|
||||
} else {
|
||||
BN_set_word(*this, -x);
|
||||
BN_set_negative(*this, 1);
|
||||
}
|
||||
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 Number::SetModInverse(const Number &x, const Number &m) {
|
||||
Context ctx;
|
||||
BN_mod_inverse(*this, x, m, ctx);
|
||||
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 Number::SetModMul(const Number &a, const Number &b, const Number &m) {
|
||||
Context ctx;
|
||||
BN_mod_mul(*this, a, b, m, ctx);
|
||||
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 Number::SetAdd(const Number &a1, const Number &a2) {
|
||||
BN_add(*this, a1, a2);
|
||||
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 Number::SetSub(const Number &a1, const Number &a2) {
|
||||
BN_sub(*this, a1, a2);
|
||||
void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
BN_nnmod(&r->bn, &a->bn, &b->bn, ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
void Number::SetMult(const Number &a1, const Number &a2) {
|
||||
Context ctx;
|
||||
BN_mul(*this, a1, a2, ctx);
|
||||
int static secp256k1_num_bits(const secp256k1_num_t *a) {
|
||||
return BN_num_bits(&a->bn);
|
||||
}
|
||||
|
||||
void Number::SetDiv(const Number &a1, const Number &a2) {
|
||||
Context ctx;
|
||||
BN_div(*this, NULL, a1, a2, ctx);
|
||||
}
|
||||
|
||||
void Number::SetMod(const Number &a, const Number &m) {
|
||||
Context ctx;
|
||||
BN_nnmod(*this, a, m, ctx);
|
||||
}
|
||||
|
||||
int Number::Compare(const Number &a) const {
|
||||
return BN_cmp(*this, a);
|
||||
}
|
||||
|
||||
int Number::GetBits() const {
|
||||
return BN_num_bits(*this);
|
||||
}
|
||||
|
||||
int Number::ShiftLowBits(int bits) {
|
||||
BIGNUM *bn = *this;
|
||||
int ret = BN_is_zero(bn) ? 0 : bn->d[0] & ((1 << bits) - 1);
|
||||
BN_rshift(*this, *this, bits);
|
||||
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;
|
||||
}
|
||||
|
||||
bool Number::IsZero() const {
|
||||
return BN_is_zero((const BIGNUM*)*this);
|
||||
int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
|
||||
return BN_is_zero(&a->bn);
|
||||
}
|
||||
|
||||
bool Number::IsOdd() const {
|
||||
return BN_is_odd((const BIGNUM*)*this);
|
||||
int static secp256k1_num_is_odd(const secp256k1_num_t *a) {
|
||||
return BN_is_odd(&a->bn);
|
||||
}
|
||||
|
||||
bool Number::CheckBit(int pos) const {
|
||||
return BN_is_bit_set((const BIGNUM*)*this, pos);
|
||||
int static secp256k1_num_is_neg(const secp256k1_num_t *a) {
|
||||
return BN_is_negative(&a->bn);
|
||||
}
|
||||
|
||||
bool Number::IsNeg() const {
|
||||
return BN_is_negative((const BIGNUM*)*this);
|
||||
int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
|
||||
return BN_is_bit_set(&a->bn, pos);
|
||||
}
|
||||
|
||||
void Number::Negate() {
|
||||
BN_set_negative(*this, !IsNeg());
|
||||
void static secp256k1_num_inc(secp256k1_num_t *r) {
|
||||
BN_add_word(&r->bn, 1);
|
||||
}
|
||||
|
||||
void Number::Shift1() {
|
||||
BN_rshift1(*this,*this);
|
||||
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 Number::Inc() {
|
||||
BN_add_word(*this,1);
|
||||
}
|
||||
|
||||
void Number::SetHex(const std::string &str) {
|
||||
BIGNUM *bn = *this;
|
||||
BN_hex2bn(&bn, str.c_str());
|
||||
}
|
||||
|
||||
void Number::SetPseudoRand(const Number &max) {
|
||||
BN_pseudo_rand_range(*this, max);
|
||||
}
|
||||
|
||||
void Number::SplitInto(int bits, Number &low, Number &high) const {
|
||||
BN_copy(low, *this);
|
||||
BN_mask_bits(low, bits);
|
||||
BN_rshift(high, *this, bits);
|
||||
}
|
||||
|
||||
std::string Number::ToString() const {
|
||||
char *str = BN_bn2hex(*this);
|
||||
std::string ret(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) + 1;
|
||||
if (len > *rlen) {
|
||||
*rlen = strlen(str);
|
||||
OPENSSL_free(str);
|
||||
return;
|
||||
}
|
||||
memcpy(r, str, len);
|
||||
OPENSSL_free(str);
|
||||
return ret;
|
||||
*rlen = len;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void static secp256k1_num_set_rand(secp256k1_num_t *r, const secp256k1_num_t *a) {
|
||||
BN_pseudo_rand_range(&r->bn, &a->bn);
|
||||
}
|
||||
|
|
|
@ -1,50 +1,10 @@
|
|||
#ifndef _SECP256K1_NUM_OPENSSL_
|
||||
#define _SECP256K1_NUM_OPENSSL_
|
||||
|
||||
#include <string>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
namespace secp256k1 {
|
||||
|
||||
class Number {
|
||||
private:
|
||||
BIGNUM b;
|
||||
Number(const Number &x);
|
||||
|
||||
operator const BIGNUM*() const;
|
||||
operator BIGNUM*();
|
||||
public:
|
||||
Number();
|
||||
~Number();
|
||||
Number(const unsigned char *bin, int len);
|
||||
void SetNumber(const Number &x);
|
||||
Number &operator=(const Number &x);
|
||||
void SetBytes(const unsigned char *bin, int len);
|
||||
void GetBytes(unsigned char *bin, int len);
|
||||
void SetInt(int x);
|
||||
void SetModInverse(const Number &x, const Number &m);
|
||||
void SetModMul(const Number &a, const Number &b, const Number &m);
|
||||
void SetAdd(const Number &a1, const Number &a2);
|
||||
void SetSub(const Number &a1, const Number &a2);
|
||||
void SetMult(const Number &a1, const Number &a2);
|
||||
void SetDiv(const Number &a1, const Number &a2);
|
||||
void SetMod(const Number &a, const Number &m);
|
||||
int Compare(const Number &a) const;
|
||||
int GetBits() const;
|
||||
int ShiftLowBits(int bits);
|
||||
bool IsZero() const;
|
||||
bool IsOdd() const;
|
||||
bool IsNeg() const;
|
||||
bool CheckBit(int pos) const;
|
||||
void Negate();
|
||||
void Shift1();
|
||||
void Inc();
|
||||
void SetHex(const std::string &str);
|
||||
void SetPseudoRand(const Number &max);
|
||||
void SplitInto(int bits, Number &low, Number &high) const;
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
}
|
||||
typedef struct {
|
||||
BIGNUM bn;
|
||||
} secp256k1_num_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,22 +7,31 @@
|
|||
namespace secp256k1 {
|
||||
|
||||
int VerifyECDSA(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
|
||||
Number m;
|
||||
int ret = -3;
|
||||
secp256k1_num_t m;
|
||||
secp256k1_num_init(&m);
|
||||
Signature s;
|
||||
GroupElemJac q;
|
||||
m.SetBytes(msg, msglen);
|
||||
if (!ParsePubKey(q, pubkey, pubkeylen))
|
||||
return -1;
|
||||
secp256k1_num_set_bin(&m, msg, msglen);
|
||||
if (!ParsePubKey(q, pubkey, pubkeylen)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
if (!s.Parse(sig, siglen)) {
|
||||
fprintf(stderr, "Can't parse signature: ");
|
||||
for (int i=0; i<siglen; i++) fprintf(stderr,"%02x", sig[i]);
|
||||
fprintf(stderr, "\n");
|
||||
return -2;
|
||||
ret = -2;
|
||||
goto end;
|
||||
}
|
||||
// fprintf(stderr, "Verifying ECDSA: msg=%s pubkey=%s sig=%s\n", m.ToString().c_str(), q.ToString().c_str(), s.ToString().c_str());
|
||||
if (!s.Verify(q, m))
|
||||
return 0;
|
||||
return 1;
|
||||
if (!s.Verify(q, m)) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
secp256k1_num_free(&m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
119
tests.cpp
119
tests.cpp
|
@ -6,6 +6,9 @@
|
|||
#include "ecmult.cpp"
|
||||
#include "ecdsa.cpp"
|
||||
|
||||
// #define COUNT 2
|
||||
#define COUNT 100
|
||||
|
||||
using namespace secp256k1;
|
||||
|
||||
void test_run_ecmult_chain() {
|
||||
|
@ -14,36 +17,56 @@ void test_run_ecmult_chain() {
|
|||
FieldElem ay; ay.SetHex("a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f");
|
||||
GroupElemJac a(ax,ay);
|
||||
// two random initial factors xn and gn
|
||||
Number xn; xn.SetHex("84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407");
|
||||
Number gn; gn.SetHex("a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de");
|
||||
secp256k1_num_t xn;
|
||||
secp256k1_num_init(&xn);
|
||||
secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
|
||||
secp256k1_num_t gn;
|
||||
secp256k1_num_init(&gn);
|
||||
secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
|
||||
// two small multipliers to be applied to xn and gn in every iteration:
|
||||
Number xf; xf.SetHex("1337");
|
||||
Number gf; gf.SetHex("7113");
|
||||
secp256k1_num_t xf;
|
||||
secp256k1_num_init(&xf);
|
||||
secp256k1_num_set_hex(&xf, "1337", 4);
|
||||
secp256k1_num_t gf;
|
||||
secp256k1_num_init(&gf);
|
||||
secp256k1_num_set_hex(&gf, "7113", 4);
|
||||
// accumulators with the resulting coefficients to A and G
|
||||
Number ae; ae.SetHex("01");
|
||||
Number ge; ge.SetHex("00");
|
||||
secp256k1_num_t ae;
|
||||
secp256k1_num_init(&ae);
|
||||
secp256k1_num_set_int(&ae, 1);
|
||||
secp256k1_num_t ge;
|
||||
secp256k1_num_init(&ge);
|
||||
secp256k1_num_set_int(&ge, 0);
|
||||
// the point being computed
|
||||
GroupElemJac x = a;
|
||||
const Number &order = GetGroupConst().order;
|
||||
for (int i=0; i<20000; i++) {
|
||||
const secp256k1_num_t &order = GetGroupConst().order;
|
||||
for (int i=0; i<200*COUNT; i++) {
|
||||
// in each iteration, compute X = xn*X + gn*G;
|
||||
ECMult(x, x, xn, gn);
|
||||
// also compute ae and ge: the actual accumulated factors for A and G
|
||||
// if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
|
||||
ae.SetModMul(ae, xn, order);
|
||||
ge.SetModMul(ge, xn, order);
|
||||
ge.SetAdd(ge, gn);
|
||||
ge.SetMod(ge, order);
|
||||
secp256k1_num_mod_mul(&ae, &ae, &xn, &order);
|
||||
secp256k1_num_mod_mul(&ge, &ge, &xn, &order);
|
||||
secp256k1_num_add(&ge, &ge, &gn);
|
||||
secp256k1_num_mod(&ge, &ge, &order);
|
||||
// modify xn and gn
|
||||
xn.SetModMul(xn, xf, order);
|
||||
gn.SetModMul(gn, gf, order);
|
||||
secp256k1_num_mod_mul(&xn, &xn, &xf, &order);
|
||||
secp256k1_num_mod_mul(&gn, &gn, &gf, &order);
|
||||
}
|
||||
std::string res = x.ToString();
|
||||
assert(res == "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)");
|
||||
if (COUNT == 100) {
|
||||
assert(res == "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)");
|
||||
}
|
||||
// redo the computation, but directly with the resulting ae and ge coefficients:
|
||||
GroupElemJac x2; ECMult(x2, a, ae, ge);
|
||||
std::string res2 = x2.ToString();
|
||||
assert(res == res2);
|
||||
secp256k1_num_free(&xn);
|
||||
secp256k1_num_free(&gn);
|
||||
secp256k1_num_free(&xf);
|
||||
secp256k1_num_free(&gf);
|
||||
secp256k1_num_free(&ae);
|
||||
secp256k1_num_free(&ge);
|
||||
}
|
||||
|
||||
void test_point_times_order(const GroupElemJac &point) {
|
||||
|
@ -52,10 +75,13 @@ void test_point_times_order(const GroupElemJac &point) {
|
|||
return;
|
||||
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
Number zero; zero.SetInt(0);
|
||||
secp256k1_num_t zero;
|
||||
secp256k1_num_init(&zero);
|
||||
secp256k1_num_set_int(&zero, 0);
|
||||
GroupElemJac res;
|
||||
ECMult(res, point, c.order, zero); // calc res = order * point + 0 * G;
|
||||
assert(res.IsInfinity());
|
||||
secp256k1_num_free(&zero);
|
||||
}
|
||||
|
||||
void test_run_point_times_order() {
|
||||
|
@ -68,14 +94,17 @@ void test_run_point_times_order() {
|
|||
assert(x.ToString() == "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45"); // 0x02 ^ (2^500)
|
||||
}
|
||||
|
||||
void test_wnaf(const Number &number, int w) {
|
||||
Number x, two, t;
|
||||
x.SetInt(0);
|
||||
two.SetInt(2);
|
||||
void test_wnaf(const secp256k1_num_t &number, int w) {
|
||||
secp256k1_num_t x, two, t;
|
||||
secp256k1_num_init(&x);
|
||||
secp256k1_num_init(&two);
|
||||
secp256k1_num_init(&t);
|
||||
secp256k1_num_set_int(&x, 0);
|
||||
secp256k1_num_set_int(&two, 2);
|
||||
WNAF<1023> wnaf(number, w);
|
||||
int zeroes = -1;
|
||||
for (int i=wnaf.GetSize()-1; i>=0; i--) {
|
||||
x.SetMult(x, two);
|
||||
secp256k1_num_mul(&x, &x, &two);
|
||||
int v = wnaf.Get(i);
|
||||
if (v) {
|
||||
assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
|
||||
|
@ -87,44 +116,64 @@ void test_wnaf(const Number &number, int w) {
|
|||
assert(zeroes != -1); // check that no unnecessary zero padding exists
|
||||
zeroes++;
|
||||
}
|
||||
t.SetInt(v);
|
||||
x.SetAdd(x, t);
|
||||
secp256k1_num_set_int(&t, v);
|
||||
secp256k1_num_add(&x, &x, &t);
|
||||
}
|
||||
assert(x.Compare(number) == 0); // check that wnaf represents number
|
||||
assert(secp256k1_num_cmp(&x, &number) == 0); // check that wnaf represents number
|
||||
secp256k1_num_free(&x);
|
||||
secp256k1_num_free(&two);
|
||||
secp256k1_num_free(&t);
|
||||
}
|
||||
|
||||
void test_run_wnaf() {
|
||||
Number range, min, n;
|
||||
range.SetHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); // 2^1024-1
|
||||
min = range; min.Shift1(); min.Negate();
|
||||
for (int i=0; i<100; i++) {
|
||||
n.SetPseudoRand(range); n.SetAdd(n,min);
|
||||
secp256k1_num_t range, min, n;
|
||||
secp256k1_num_init(&range);
|
||||
secp256k1_num_init(&min);
|
||||
secp256k1_num_init(&n);
|
||||
secp256k1_num_set_hex(&range, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 256);
|
||||
secp256k1_num_copy(&min, &range);
|
||||
secp256k1_num_shift(&min, 1);
|
||||
secp256k1_num_negate(&min);
|
||||
for (int i=0; i<COUNT; i++) {
|
||||
secp256k1_num_set_rand(&n, &range);
|
||||
secp256k1_num_add(&n, &n, &min);
|
||||
test_wnaf(n, 4+(i%10));
|
||||
}
|
||||
secp256k1_num_free(&range);
|
||||
secp256k1_num_free(&min);
|
||||
secp256k1_num_free(&n);
|
||||
}
|
||||
|
||||
void test_ecdsa_sign_verify() {
|
||||
const GroupConstants &c = GetGroupConst();
|
||||
Number msg; msg.SetPseudoRand(c.order);
|
||||
Number key; key.SetPseudoRand(c.order);
|
||||
Number nonce;
|
||||
secp256k1_num_t msg, key, nonce;
|
||||
secp256k1_num_init(&msg);
|
||||
secp256k1_num_set_rand(&msg, &c.order);
|
||||
secp256k1_num_init(&key);
|
||||
secp256k1_num_set_rand(&key, &c.order);
|
||||
secp256k1_num_init(&nonce);
|
||||
GroupElemJac pub; ECMultBase(pub, key);
|
||||
Signature sig;
|
||||
do {
|
||||
nonce.SetPseudoRand(c.order);
|
||||
secp256k1_num_set_rand(&nonce, &c.order);
|
||||
} while(!sig.Sign(key, msg, nonce));
|
||||
assert(sig.Verify(pub, msg));
|
||||
msg.Inc();
|
||||
secp256k1_num_inc(&msg);
|
||||
assert(!sig.Verify(pub, msg));
|
||||
secp256k1_num_free(&msg);
|
||||
secp256k1_num_free(&key);
|
||||
secp256k1_num_free(&nonce);
|
||||
}
|
||||
|
||||
void test_run_ecdsa_sign_verify() {
|
||||
for (int i=0; i<1000; i++) {
|
||||
for (int i=0; i<10*COUNT; i++) {
|
||||
test_ecdsa_sign_verify();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
secp256k1_num_start();
|
||||
|
||||
test_run_wnaf();
|
||||
test_run_point_times_order();
|
||||
test_run_ecmult_chain();
|
||||
|
|
Loading…
Reference in New Issue