2013-03-07 22:52:50 -03:00
|
|
|
#ifndef _SECP256K1_ECMULT_
|
|
|
|
#define _SECP256K1_ECMULT_
|
|
|
|
|
2013-03-09 18:47:40 -03:00
|
|
|
#include <sstream>
|
|
|
|
#include <algorithm>
|
|
|
|
|
2013-03-07 22:52:50 -03:00
|
|
|
#include "group.h"
|
|
|
|
#include "scalar.h"
|
|
|
|
|
2013-03-09 21:49:42 -03:00
|
|
|
#define WINDOW_A 5
|
|
|
|
#define WINDOW_G 11
|
|
|
|
|
2013-03-07 22:52:50 -03:00
|
|
|
namespace secp256k1 {
|
|
|
|
|
|
|
|
template<typename G, int W> class WNAFPrecomp {
|
|
|
|
private:
|
|
|
|
G pre[1 << (W-2)];
|
|
|
|
|
|
|
|
public:
|
2013-03-09 18:47:40 -03:00
|
|
|
WNAFPrecomp(const G &base) {
|
2013-03-07 22:52:50 -03:00
|
|
|
pre[0] = base;
|
2013-03-09 21:49:42 -03:00
|
|
|
GroupElemJac x(base);
|
|
|
|
// printf("base=%s x=%s\n", base.ToString().c_str(), x.ToString().c_str());
|
2013-03-07 22:52:50 -03:00
|
|
|
GroupElemJac d; d.SetDouble(x);
|
2013-03-09 21:49:42 -03:00
|
|
|
// printf("d=%s\n", d.ToString().c_str());
|
2013-03-07 22:52:50 -03:00
|
|
|
for (int i=1; i<(1 << (W-2)); i++) {
|
|
|
|
x.SetAdd(d,pre[i-1]);
|
2013-03-09 18:47:40 -03:00
|
|
|
pre[i].SetJac(x);
|
2013-03-09 21:49:42 -03:00
|
|
|
// printf("precomp %s*%i = %s\n", base.ToString().c_str(), i*2 +1, pre[i].ToString().c_str());
|
2013-03-07 22:52:50 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:47:40 -03:00
|
|
|
void Get(G &out, int exp) const {
|
2013-03-07 22:52:50 -03:00
|
|
|
assert((exp & 1) == 1);
|
|
|
|
assert(exp >= -((1 << (W-1)) - 1));
|
|
|
|
assert(exp <= ((1 << (W-1)) - 1));
|
|
|
|
if (exp > 0) {
|
|
|
|
out = pre[(exp-1)/2];
|
|
|
|
} else {
|
2013-03-09 21:49:42 -03:00
|
|
|
out.SetNeg(pre[(-exp-1)/2]);
|
2013-03-07 22:52:50 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-03-09 18:47:40 -03:00
|
|
|
template<int B> class WNAF {
|
2013-03-07 22:52:50 -03:00
|
|
|
private:
|
2013-03-09 18:47:40 -03:00
|
|
|
int naf[B+1];
|
|
|
|
int used;
|
|
|
|
|
|
|
|
void PushNAF(int num, int zeroes) {
|
|
|
|
for (int i=0; i<zeroes; i++) {
|
|
|
|
naf[used++]=0;
|
|
|
|
}
|
|
|
|
naf[used++]=num;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2013-03-09 21:49:42 -03:00
|
|
|
WNAF(Context &ctx, const Scalar &exp, int w) : used(0) {
|
2013-03-09 18:47:40 -03:00
|
|
|
int zeroes = 0;
|
2013-03-09 21:49:42 -03:00
|
|
|
Context ct(ctx);
|
|
|
|
Scalar x(ct);
|
|
|
|
x.SetNumber(exp);
|
|
|
|
while (!x.IsZero()) {
|
|
|
|
while (!x.IsOdd()) {
|
2013-03-09 18:47:40 -03:00
|
|
|
zeroes++;
|
2013-03-09 21:49:42 -03:00
|
|
|
x.Shift1();
|
2013-03-09 18:47:40 -03:00
|
|
|
}
|
2013-03-09 21:49:42 -03:00
|
|
|
int word = x.ShiftLowBits(ctx,w);
|
2013-03-09 18:47:40 -03:00
|
|
|
if (word & (1 << (w-1))) {
|
2013-03-09 21:49:42 -03:00
|
|
|
x.Inc();
|
2013-03-09 18:47:40 -03:00
|
|
|
PushNAF(word - (1 << w), zeroes);
|
|
|
|
} else {
|
|
|
|
PushNAF(word, zeroes);
|
|
|
|
}
|
|
|
|
zeroes = w-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetSize() const {
|
|
|
|
return used;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Get(int pos) const {
|
2013-03-09 21:49:42 -03:00
|
|
|
assert(pos >= 0 && pos < used);
|
|
|
|
return naf[pos];
|
2013-03-09 18:47:40 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string ToString() {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "(";
|
|
|
|
for (int i=0; i<GetSize(); i++) {
|
2013-03-09 21:49:42 -03:00
|
|
|
ss << Get(used-1-i);
|
2013-03-09 18:47:40 -03:00
|
|
|
if (i != used-1)
|
|
|
|
ss << ',';
|
|
|
|
}
|
|
|
|
ss << ")";
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ECMultConsts {
|
|
|
|
public:
|
2013-03-09 21:49:42 -03:00
|
|
|
const WNAFPrecomp<GroupElem,WINDOW_G> wpg;
|
2013-03-07 22:52:50 -03:00
|
|
|
|
2013-03-09 18:47:40 -03:00
|
|
|
ECMultConsts() : wpg(GetGroupConst().g) {}
|
2013-03-07 22:52:50 -03:00
|
|
|
};
|
|
|
|
|
2013-03-09 18:47:40 -03:00
|
|
|
const ECMultConsts &GetECMultConsts() {
|
|
|
|
static const ECMultConsts ecmult_consts;
|
|
|
|
return ecmult_consts;
|
|
|
|
}
|
|
|
|
|
2013-03-09 21:49:42 -03:00
|
|
|
void ECMult(Context &ctx, GroupElemJac &out, const GroupElemJac &a, Scalar &an, Scalar &gn) {
|
|
|
|
WNAF<256> wa(ctx, an, WINDOW_A);
|
|
|
|
WNAF<256> wg(ctx, gn, WINDOW_G);
|
|
|
|
WNAFPrecomp<GroupElemJac,WINDOW_A> wpa(a);
|
|
|
|
const WNAFPrecomp<GroupElem,WINDOW_G> &wpg = GetECMultConsts().wpg;
|
2013-03-09 18:47:40 -03:00
|
|
|
|
2013-03-09 21:49:42 -03:00
|
|
|
int size_a = wa.GetSize();
|
|
|
|
int size_g = wg.GetSize();
|
|
|
|
int size = std::max(size_a, size_g);
|
2013-03-09 18:47:40 -03:00
|
|
|
|
|
|
|
out = GroupElemJac();
|
|
|
|
GroupElemJac tmpj;
|
|
|
|
GroupElem tmpa;
|
|
|
|
|
2013-03-09 21:49:42 -03:00
|
|
|
for (int i=size-1; i>=0; i--) {
|
2013-03-09 18:47:40 -03:00
|
|
|
out.SetDouble(out);
|
2013-03-09 21:49:42 -03:00
|
|
|
int nw;
|
|
|
|
if (i < size_a && (nw = wa.Get(i))) {
|
|
|
|
wpa.Get(tmpj, nw);
|
2013-03-09 18:47:40 -03:00
|
|
|
out.SetAdd(out, tmpj);
|
|
|
|
}
|
2013-03-09 21:49:42 -03:00
|
|
|
if (i < size_g && (nw = wg.Get(i))) {
|
|
|
|
wpg.Get(tmpa, nw);
|
2013-03-09 18:47:40 -03:00
|
|
|
out.SetAdd(out, tmpa);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-07 22:52:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|