129 lines
3.4 KiB
C++
129 lines
3.4 KiB
C++
#include "num.h"
|
|
#include "field.h"
|
|
#include "group.h"
|
|
#include "ecmult.h"
|
|
#include "ecdsa.h"
|
|
|
|
namespace secp256k1 {
|
|
|
|
bool ParsePubKey(GroupElemJac &elem, const unsigned char *pub, int size) {
|
|
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
|
|
FieldElem x;
|
|
x.SetBytes(pub+1);
|
|
elem.SetCompressed(x, pub[0] == 0x03);
|
|
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
|
|
FieldElem x,y;
|
|
x.SetBytes(pub+1);
|
|
y.SetBytes(pub+33);
|
|
elem = GroupElem(x,y);
|
|
if ((pub[0] == 0x06 || pub[0] == 0x07) && y.IsOdd() != (pub[0] == 0x07))
|
|
return false;
|
|
} else {
|
|
return false;
|
|
}
|
|
return elem.IsValid();
|
|
}
|
|
|
|
bool Signature::Parse(const unsigned char *sig, int size) {
|
|
if (sig[0] != 0x30) return false;
|
|
int lenr = sig[3];
|
|
if (5+lenr >= size) return false;
|
|
int lens = sig[lenr+5];
|
|
if (sig[1] != lenr+lens+4) return false;
|
|
if (lenr+lens+6 > size) return false;
|
|
if (sig[2] != 0x02) return false;
|
|
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);
|
|
return true;
|
|
}
|
|
|
|
bool Signature::Serialize(unsigned char *sig, int *size) {
|
|
int lenR = (r.GetBits() + 7)/8;
|
|
if (lenR == 0 || r.CheckBit(lenR*8-1))
|
|
lenR++;
|
|
int lenS = (s.GetBits() + 7)/8;
|
|
if (lenS == 0 || s.CheckBit(lenS*8-1))
|
|
lenS++;
|
|
if (*size < 6+lenS+lenR)
|
|
return false;
|
|
*size = 6 + lenS + lenR;
|
|
sig[0] = 0x30;
|
|
sig[1] = 4 + lenS + lenR;
|
|
sig[2] = 0x02;
|
|
sig[3] = lenR;
|
|
r.GetBytes(sig+4, lenR);
|
|
sig[4+lenR] = 0x02;
|
|
sig[5+lenR] = lenS;
|
|
s.GetBytes(sig+6, lenS);
|
|
return true;
|
|
}
|
|
|
|
bool Signature::RecomputeR(Number &r2, const GroupElemJac &pubkey, const Number &message) const {
|
|
const GroupConstants &c = GetGroupConst();
|
|
|
|
if (r.IsNeg() || s.IsNeg())
|
|
return false;
|
|
if (r.IsZero() || s.IsZero())
|
|
return false;
|
|
if (r.Compare(c.order) >= 0 || s.Compare(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);
|
|
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;
|
|
}
|
|
|
|
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::Sign(const Number &seckey, const Number &message, const Number &nonce) {
|
|
const GroupConstants &c = GetGroupConst();
|
|
|
|
GroupElemJac rp;
|
|
ECMultBase(rp, nonce);
|
|
FieldElem rx;
|
|
rp.GetX(rx);
|
|
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())
|
|
return false;
|
|
if (s.IsOdd())
|
|
s.SetSub(c.order, s);
|
|
return true;
|
|
}
|
|
|
|
void Signature::SetRS(const Number &rin, const Number &sin) {
|
|
r = rin;
|
|
s = sin;
|
|
}
|
|
|
|
std::string Signature::ToString() const {
|
|
return "(" + r.ToString() + "," + s.ToString() + ")";
|
|
}
|
|
|
|
}
|