keyhunt/secp256k1/SECP256K1.cpp

791 lines
18 KiB
C++

/*
* This file is part of the BSGS distribution (https://github.com/JeanLucPons/BSGS).
* Copyright (c) 2020 Jean Luc PONS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include <cstring>
#include "SECP256k1.h"
#include "Point.h"
#include "../util.h"
#include "../hash/sha256.h"
#include "../hash/ripemd160.h"
Secp256K1::Secp256K1() {
}
void Secp256K1::Init() {
// Prime for the finite field
P.SetBase16("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
// Set up field
Int::SetupField(&P);
// Generator point and order
G.x.SetBase16("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798");
G.y.SetBase16("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
G.z.SetInt32(1);
order.SetBase16("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
Int::InitK1(&order);
// Compute Generator table
Point N(G);
for(int i = 0; i < 32; i++) {
GTable[i * 256] = N;
N = DoubleDirect(N);
for (int j = 1; j < 255; j++) {
GTable[i * 256 + j] = N;
N = AddDirect(N, GTable[i * 256]);
}
GTable[i * 256 + 255] = N; // Dummy point for check function
}
}
Secp256K1::~Secp256K1() {
}
Point Secp256K1::ComputePublicKey(Int *privKey) {
int i = 0;
uint8_t b;
Point Q;
Q.Clear();
// Search first significant byte
for (i = 0; i < 32; i++) {
b = privKey->GetByte(i);
if(b)
break;
}
Q = GTable[256 * i + (b-1)];
i++;
for(; i < 32; i++) {
b = privKey->GetByte(i);
if(b)
Q = Add2(Q, GTable[256 * i + (b-1)]);
}
Q.Reduce();
return Q;
}
Point Secp256K1::NextKey(Point &key) {
// Input key must be reduced and different from G
// in order to use AddDirect
return AddDirect(key,G);
}
uint8_t Secp256K1::GetByte(char *str, int idx) {
char tmp[3];
int val;
tmp[0] = str[2 * idx];
tmp[1] = str[2 * idx + 1];
tmp[2] = 0;
if (sscanf(tmp, "%X", &val) != 1) {
printf("ParsePublicKeyHex: Error invalid public key specified (unexpected hexadecimal digit)\n");
exit(-1);
}
return (uint8_t)val;
}
Point Secp256K1::Negation(Point &p) {
Point Q;
Q.Clear();
Q.x.Set(&p.x);
Q.y.Set(&this->P);
Q.y.Sub(&p.y);
Q.z.SetInt32(1);
return Q;
}
bool Secp256K1::ParsePublicKeyHex(char *str,Point &ret,bool &isCompressed) {
int len = strlen(str);
ret.Clear();
if (len < 2) {
printf("ParsePublicKeyHex: Error invalid public key specified (66 or 130 character length)\n");
return false;
}
uint8_t type = GetByte(str, 0);
switch (type) {
case 0x02:
if (len != 66) {
printf("ParsePublicKeyHex: Error invalid public key specified (66 character length)\n");
return false;
}
for (int i = 0; i < 32; i++)
ret.x.SetByte(31 - i, GetByte(str, i + 1));
ret.y = GetY(ret.x, true);
isCompressed = true;
break;
case 0x03:
if (len != 66) {
printf("ParsePublicKeyHex: Error invalid public key specified (66 character length)\n");
return false;
}
for (int i = 0; i < 32; i++)
ret.x.SetByte(31 - i, GetByte(str, i + 1));
ret.y = GetY(ret.x, false);
isCompressed = true;
break;
case 0x04:
if (len != 130) {
printf("ParsePublicKeyHex: Error invalid public key specified (130 character length)\n");
exit(-1);
}
for (int i = 0; i < 32; i++)
ret.x.SetByte(31 - i, GetByte(str, i + 1));
for (int i = 0; i < 32; i++)
ret.y.SetByte(31 - i, GetByte(str, i + 33));
isCompressed = false;
break;
default:
printf("ParsePublicKeyHex: Error invalid public key specified (Unexpected prefix (only 02,03 or 04 allowed)\n");
return false;
}
ret.z.SetInt32(1);
if (!EC(ret)) {
printf("ParsePublicKeyHex: Error invalid public key specified (Not lie on elliptic curve)\n");
return false;
}
return true;
}
char* Secp256K1::GetPublicKeyHex(bool compressed, Point &pubKey) {
unsigned char publicKeyBytes[65];
char *ret = NULL;
if (!compressed) {
//Uncompressed public key
publicKeyBytes[0] = 0x4;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
pubKey.y.Get32Bytes(publicKeyBytes + 33);
ret = (char*) tohex((char*)publicKeyBytes,65);
}
else {
// Compressed public key
publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
ret = (char*) tohex((char*)publicKeyBytes,33);
}
return ret;
}
void Secp256K1::GetPublicKeyHex(bool compressed, Point &pubKey,char *dst){
unsigned char publicKeyBytes[65];
if (!compressed) {
//Uncompressed public key
publicKeyBytes[0] = 0x4;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
pubKey.y.Get32Bytes(publicKeyBytes + 33);
tohex_dst((char*)publicKeyBytes,65,dst);
}
else {
// Compressed public key
publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
tohex_dst((char*)publicKeyBytes,33,dst);
}
}
char* Secp256K1::GetPublicKeyRaw(bool compressed, Point &pubKey) {
char *ret = (char*) malloc(65);
if(ret == NULL) {
::fprintf(stderr,"Can't alloc memory\n");
exit(0);
}
if (!compressed) {
//Uncompressed public key
ret[0] = 0x4;
pubKey.x.Get32Bytes((unsigned char*) (ret + 1));
pubKey.y.Get32Bytes((unsigned char*) (ret + 33));
}
else {
// Compressed public key
ret[0] = pubKey.y.IsEven() ? 0x2 : 0x3;
pubKey.x.Get32Bytes((unsigned char*) (ret + 1));
}
return ret;
}
void Secp256K1::GetPublicKeyRaw(bool compressed, Point &pubKey,char *dst) {
if (!compressed) {
//Uncompressed public key
dst[0] = 0x4;
pubKey.x.Get32Bytes((unsigned char*) (dst + 1));
pubKey.y.Get32Bytes((unsigned char*) (dst + 33));
}
else {
// Compressed public key
dst[0] = pubKey.y.IsEven() ? 0x2 : 0x3;
pubKey.x.Get32Bytes((unsigned char*) (dst + 1));
}
}
Point Secp256K1::AddDirect(Point &p1,Point &p2) {
Int _s;
Int _p;
Int dy;
Int dx;
Point r;
r.z.SetInt32(1);
dy.ModSub(&p2.y,&p1.y);
dx.ModSub(&p2.x,&p1.x);
dx.ModInv();
_s.ModMulK1(&dy,&dx); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
_p.ModSquareK1(&_s); // _p = pow2(s)
r.x.ModSub(&_p,&p1.x);
r.x.ModSub(&p2.x); // rx = pow2(s) - p1.x - p2.x;
r.y.ModSub(&p2.x,&r.x);
r.y.ModMulK1(&_s);
r.y.ModSub(&p2.y); // ry = - p2.y - s*(ret.x-p2.x);
return r;
}
Point Secp256K1::Add2(Point &p1, Point &p2) {
// P2.z = 1
Int u;
Int v;
Int u1;
Int v1;
Int vs2;
Int vs3;
Int us2;
Int a;
Int us2w;
Int vs2v2;
Int vs3u2;
Int _2vs2v2;
Point r;
u1.ModMulK1(&p2.y, &p1.z);
v1.ModMulK1(&p2.x, &p1.z);
u.ModSub(&u1, &p1.y);
v.ModSub(&v1, &p1.x);
us2.ModSquareK1(&u);
vs2.ModSquareK1(&v);
vs3.ModMulK1(&vs2, &v);
us2w.ModMulK1(&us2, &p1.z);
vs2v2.ModMulK1(&vs2, &p1.x);
_2vs2v2.ModAdd(&vs2v2, &vs2v2);
a.ModSub(&us2w, &vs3);
a.ModSub(&_2vs2v2);
r.x.ModMulK1(&v, &a);
vs3u2.ModMulK1(&vs3, &p1.y);
r.y.ModSub(&vs2v2, &a);
r.y.ModMulK1(&r.y, &u);
r.y.ModSub(&vs3u2);
r.z.ModMulK1(&vs3, &p1.z);
return r;
}
Point Secp256K1::Add(Point &p1,Point &p2) {
Int u;
Int v;
Int u1;
Int u2;
Int v1;
Int v2;
Int vs2;
Int vs3;
Int us2;
Int w;
Int a;
Int us2w;
Int vs2v2;
Int vs3u2;
Int _2vs2v2;
Int x3;
Int vs3y1;
Point r;
/*
U1 = Y2 * Z1
U2 = Y1 * Z2
V1 = X2 * Z1
V2 = X1 * Z2
if (V1 == V2)
if (U1 != U2)
return POINT_AT_INFINITY
else
return POINT_DOUBLE(X1, Y1, Z1)
U = U1 - U2
V = V1 - V2
W = Z1 * Z2
A = U ^ 2 * W - V ^ 3 - 2 * V ^ 2 * V2
X3 = V * A
Y3 = U * (V ^ 2 * V2 - A) - V ^ 3 * U2
Z3 = V ^ 3 * W
return (X3, Y3, Z3)
*/
u1.ModMulK1(&p2.y,&p1.z);
u2.ModMulK1(&p1.y,&p2.z);
v1.ModMulK1(&p2.x,&p1.z);
v2.ModMulK1(&p1.x,&p2.z);
u.ModSub(&u1,&u2);
v.ModSub(&v1,&v2);
w.ModMulK1(&p1.z,&p2.z);
us2.ModSquareK1(&u);
vs2.ModSquareK1(&v);
vs3.ModMulK1(&vs2,&v);
us2w.ModMulK1(&us2,&w);
vs2v2.ModMulK1(&vs2,&v2);
_2vs2v2.ModAdd(&vs2v2,&vs2v2);
a.ModSub(&us2w,&vs3);
a.ModSub(&_2vs2v2);
r.x.ModMulK1(&v,&a);
vs3u2.ModMulK1(&vs3,&u2);
r.y.ModSub(&vs2v2,&a);
r.y.ModMulK1(&r.y,&u);
r.y.ModSub(&vs3u2);
r.z.ModMulK1(&vs3,&w);
return r;
}
Point Secp256K1::DoubleDirect(Point &p) {
Int _s;
Int _p;
Int a;
Point r;
r.z.SetInt32(1);
_s.ModMulK1(&p.x,&p.x);
_p.ModAdd(&_s,&_s);
_p.ModAdd(&_s);
a.ModAdd(&p.y,&p.y);
a.ModInv();
_s.ModMulK1(&_p,&a); // s = (3*pow2(p.x))*inverse(2*p.y);
_p.ModMulK1(&_s,&_s);
a.ModAdd(&p.x,&p.x);
a.ModNeg();
r.x.ModAdd(&a,&_p); // rx = pow2(s) + neg(2*p.x);
a.ModSub(&r.x,&p.x);
_p.ModMulK1(&a,&_s);
r.y.ModAdd(&_p,&p.y);
r.y.ModNeg(); // ry = neg(p.y + s*(ret.x+neg(p.x)));
return r;
}
Point Secp256K1::Double(Point &p) {
/*
if (Y == 0)
return POINT_AT_INFINITY
W = a * Z ^ 2 + 3 * X ^ 2
S = Y * Z
B = X * Y*S
H = W ^ 2 - 8 * B
X' = 2*H*S
Y' = W*(4*B - H) - 8*Y^2*S^2
Z' = 8*S^3
return (X', Y', Z')
*/
Int z2;
Int x2;
Int _3x2;
Int w;
Int s;
Int s2;
Int b;
Int _8b;
Int _8y2s2;
Int y2;
Int h;
Point r;
z2.ModSquareK1(&p.z);
z2.SetInt32(0); // a=0
x2.ModSquareK1(&p.x);
_3x2.ModAdd(&x2,&x2);
_3x2.ModAdd(&x2);
w.ModAdd(&z2,&_3x2);
s.ModMulK1(&p.y,&p.z);
b.ModMulK1(&p.y,&s);
b.ModMulK1(&p.x);
h.ModSquareK1(&w);
_8b.ModAdd(&b,&b);
_8b.ModDouble();
_8b.ModDouble();
h.ModSub(&_8b);
r.x.ModMulK1(&h,&s);
r.x.ModAdd(&r.x);
s2.ModSquareK1(&s);
y2.ModSquareK1(&p.y);
_8y2s2.ModMulK1(&y2,&s2);
_8y2s2.ModDouble();
_8y2s2.ModDouble();
_8y2s2.ModDouble();
r.y.ModAdd(&b,&b);
r.y.ModAdd(&r.y,&r.y);
r.y.ModSub(&h);
r.y.ModMulK1(&w);
r.y.ModSub(&_8y2s2);
r.z.ModMulK1(&s2,&s);
r.z.ModDouble();
r.z.ModDouble();
r.z.ModDouble();
return r;
}
Int Secp256K1::GetY(Int x,bool isEven) {
Int _s;
Int _p;
_s.ModSquareK1(&x);
_p.ModMulK1(&_s,&x);
_p.ModAdd(7);
_p.ModSqrt();
if(!_p.IsEven() && isEven) {
_p.ModNeg();
}
else if(_p.IsEven() && !isEven) {
_p.ModNeg();
}
return _p;
}
bool Secp256K1::EC(Point &p) {
Int _s;
Int _p;
_s.ModSquareK1(&p.x);
_p.ModMulK1(&_s,&p.x);
_p.ModAdd(7);
_s.ModMulK1(&p.y,&p.y);
_s.ModSub(&_p);
return _s.IsZero(); // ( ((pow2(y) - (pow3(x) + 7)) % P) == 0 );
}
Point Secp256K1::ScalarMultiplication(Point &P,Int *scalar) {
Point R,Q,T;
int no_of_bits, loop;
no_of_bits = scalar->GetBitLength();
R.Clear();
R.z.SetInt32(1);
if(!scalar->IsZero()) {
Q.Set(P);
if(scalar->GetBit(0) == 1) {
R.Set(P);
}
for(loop = 1; loop < no_of_bits; loop++) {
T = Double(Q);
Q.Set(T);
T.Set(R);
if(scalar->GetBit(loop)){
R = Add(T,Q);
}
}
}
R.Reduce();
return R;
}
#define KEYBUFFCOMP(buff,p) \
(buff)[0] = ((p).x.bits[7] >> 8) | ((uint32_t)(0x2 + (p).y.IsOdd()) << 24); \
(buff)[1] = ((p).x.bits[6] >> 8) | ((p).x.bits[7] <<24); \
(buff)[2] = ((p).x.bits[5] >> 8) | ((p).x.bits[6] <<24); \
(buff)[3] = ((p).x.bits[4] >> 8) | ((p).x.bits[5] <<24); \
(buff)[4] = ((p).x.bits[3] >> 8) | ((p).x.bits[4] <<24); \
(buff)[5] = ((p).x.bits[2] >> 8) | ((p).x.bits[3] <<24); \
(buff)[6] = ((p).x.bits[1] >> 8) | ((p).x.bits[2] <<24); \
(buff)[7] = ((p).x.bits[0] >> 8) | ((p).x.bits[1] <<24); \
(buff)[8] = 0x00800000 | ((p).x.bits[0] <<24); \
(buff)[9] = 0; \
(buff)[10] = 0; \
(buff)[11] = 0; \
(buff)[12] = 0; \
(buff)[13] = 0; \
(buff)[14] = 0; \
(buff)[15] = 0x108;
#define KEYBUFFUNCOMP(buff,p) \
(buff)[0] = ((p).x.bits[7] >> 8) | 0x04000000; \
(buff)[1] = ((p).x.bits[6] >> 8) | ((p).x.bits[7] <<24); \
(buff)[2] = ((p).x.bits[5] >> 8) | ((p).x.bits[6] <<24); \
(buff)[3] = ((p).x.bits[4] >> 8) | ((p).x.bits[5] <<24); \
(buff)[4] = ((p).x.bits[3] >> 8) | ((p).x.bits[4] <<24); \
(buff)[5] = ((p).x.bits[2] >> 8) | ((p).x.bits[3] <<24); \
(buff)[6] = ((p).x.bits[1] >> 8) | ((p).x.bits[2] <<24); \
(buff)[7] = ((p).x.bits[0] >> 8) | ((p).x.bits[1] <<24); \
(buff)[8] = ((p).y.bits[7] >> 8) | ((p).x.bits[0] <<24); \
(buff)[9] = ((p).y.bits[6] >> 8) | ((p).y.bits[7] <<24); \
(buff)[10] = ((p).y.bits[5] >> 8) | ((p).y.bits[6] <<24); \
(buff)[11] = ((p).y.bits[4] >> 8) | ((p).y.bits[5] <<24); \
(buff)[12] = ((p).y.bits[3] >> 8) | ((p).y.bits[4] <<24); \
(buff)[13] = ((p).y.bits[2] >> 8) | ((p).y.bits[3] <<24); \
(buff)[14] = ((p).y.bits[1] >> 8) | ((p).y.bits[2] <<24); \
(buff)[15] = ((p).y.bits[0] >> 8) | ((p).y.bits[1] <<24); \
(buff)[16] = 0x00800000 | ((p).y.bits[0] <<24); \
(buff)[17] = 0; \
(buff)[18] = 0; \
(buff)[19] = 0; \
(buff)[20] = 0; \
(buff)[21] = 0; \
(buff)[22] = 0; \
(buff)[23] = 0; \
(buff)[24] = 0; \
(buff)[25] = 0; \
(buff)[26] = 0; \
(buff)[27] = 0; \
(buff)[28] = 0; \
(buff)[29] = 0; \
(buff)[30] = 0; \
(buff)[31] = 0x208;
#define KEYBUFFSCRIPT(buff,h) \
(buff)[0] = 0x00140000 | (uint32_t)h[0] << 8 | (uint32_t)h[1]; \
(buff)[1] = (uint32_t)h[2] << 24 | (uint32_t)h[3] << 16 | (uint32_t)h[4] << 8 | (uint32_t)h[5];\
(buff)[2] = (uint32_t)h[6] << 24 | (uint32_t)h[7] << 16 | (uint32_t)h[8] << 8 | (uint32_t)h[9];\
(buff)[3] = (uint32_t)h[10] << 24 | (uint32_t)h[11] << 16 | (uint32_t)h[12] << 8 | (uint32_t)h[13];\
(buff)[4] = (uint32_t)h[14] << 24 | (uint32_t)h[15] << 16 | (uint32_t)h[16] << 8 | (uint32_t)h[17];\
(buff)[5] = (uint32_t)h[18] << 24 | (uint32_t)h[19] << 16 | 0x8000; \
(buff)[6] = 0; \
(buff)[7] = 0; \
(buff)[8] = 0; \
(buff)[9] = 0; \
(buff)[10] = 0; \
(buff)[11] = 0; \
(buff)[12] = 0; \
(buff)[13] = 0; \
(buff)[14] = 0; \
(buff)[15] = 0xB0;
void Secp256K1::GetHash160(int type,bool compressed,
Point &k0,Point &k1,Point &k2,Point &k3,
uint8_t *h0,uint8_t *h1,uint8_t *h2,uint8_t *h3) {
#ifdef WIN64
__declspec(align(16)) unsigned char sh0[64];
__declspec(align(16)) unsigned char sh1[64];
__declspec(align(16)) unsigned char sh2[64];
__declspec(align(16)) unsigned char sh3[64];
#else
unsigned char sh0[64] __attribute__((aligned(16)));
unsigned char sh1[64] __attribute__((aligned(16)));
unsigned char sh2[64] __attribute__((aligned(16)));
unsigned char sh3[64] __attribute__((aligned(16)));
#endif
switch (type) {
case P2PKH:
case BECH32:
{
if (!compressed) {
uint32_t b0[32];
uint32_t b1[32];
uint32_t b2[32];
uint32_t b3[32];
KEYBUFFUNCOMP(b0, k0);
KEYBUFFUNCOMP(b1, k1);
KEYBUFFUNCOMP(b2, k2);
KEYBUFFUNCOMP(b3, k3);
sha256sse_2B(b0, b1, b2, b3, sh0, sh1, sh2, sh3);
ripemd160sse_32(sh0, sh1, sh2, sh3, h0, h1, h2, h3);
} else {
uint32_t b0[16];
uint32_t b1[16];
uint32_t b2[16];
uint32_t b3[16];
KEYBUFFCOMP(b0, k0);
KEYBUFFCOMP(b1, k1);
KEYBUFFCOMP(b2, k2);
KEYBUFFCOMP(b3, k3);
sha256sse_1B(b0, b1, b2, b3, sh0, sh1, sh2, sh3);
ripemd160sse_32(sh0, sh1, sh2, sh3, h0, h1, h2, h3);
}
}
break;
case P2SH:
{
unsigned char kh0[20];
unsigned char kh1[20];
unsigned char kh2[20];
unsigned char kh3[20];
GetHash160(P2PKH,compressed,k0,k1,k2,k3,kh0,kh1,kh2,kh3);
// Redeem Script (1 to 1 P2SH)
uint32_t b0[16];
uint32_t b1[16];
uint32_t b2[16];
uint32_t b3[16];
KEYBUFFSCRIPT(b0, kh0);
KEYBUFFSCRIPT(b1, kh1);
KEYBUFFSCRIPT(b2, kh2);
KEYBUFFSCRIPT(b3, kh3);
sha256sse_1B(b0, b1, b2, b3, sh0, sh1, sh2, sh3);
ripemd160sse_32(sh0, sh1, sh2, sh3, h0, h1, h2, h3);
}
break;
}
}
void Secp256K1::GetHash160(int type, bool compressed, Point &pubKey, unsigned char *hash) {
unsigned char shapk[64];
switch (type) {
case P2PKH:
case BECH32:
{
unsigned char publicKeyBytes[128];
if (!compressed) {
// Full public key
publicKeyBytes[0] = 0x4;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
pubKey.y.Get32Bytes(publicKeyBytes + 33);
sha256_65(publicKeyBytes, shapk);
} else {
// Compressed public key
publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3;
pubKey.x.Get32Bytes(publicKeyBytes + 1);
sha256_33(publicKeyBytes, shapk);
}
ripemd160_32(shapk, hash);
}
break;
case P2SH:
{
// Redeem Script (1 to 1 P2SH)
unsigned char script[64];
script[0] = 0x00; // OP_0
script[1] = 0x14; // PUSH 20 bytes
GetHash160(P2PKH, compressed, pubKey, script + 2);
sha256(script, 22, shapk);
ripemd160_32(shapk, hash);
}
break;
}
}
#define KEYBUFFPREFIX(buff,k,fix) \
(buff)[0] = (k->bits[7] >> 8) | ((uint32_t)(fix) << 24); \
(buff)[1] = (k->bits[6] >> 8) | (k->bits[7] <<24); \
(buff)[2] = (k->bits[5] >> 8) | (k->bits[6] <<24); \
(buff)[3] = (k->bits[4] >> 8) | (k->bits[5] <<24); \
(buff)[4] = (k->bits[3] >> 8) | (k->bits[4] <<24); \
(buff)[5] = (k->bits[2] >> 8) | (k->bits[3] <<24); \
(buff)[6] = (k->bits[1] >> 8) | (k->bits[2] <<24); \
(buff)[7] = (k->bits[0] >> 8) | (k->bits[1] <<24); \
(buff)[8] = 0x00800000 | (k->bits[0] <<24); \
(buff)[9] = 0; \
(buff)[10] = 0; \
(buff)[11] = 0; \
(buff)[12] = 0; \
(buff)[13] = 0; \
(buff)[14] = 0; \
(buff)[15] = 0x108;
void Secp256K1::GetHash160_fromX(int type,unsigned char prefix,
Int *k0,Int *k1,Int *k2,Int *k3,
uint8_t *h0,uint8_t *h1,uint8_t *h2,uint8_t *h3) {
#ifdef WIN64
__declspec(align(16)) unsigned char sh0[64];
__declspec(align(16)) unsigned char sh1[64];
__declspec(align(16)) unsigned char sh2[64];
__declspec(align(16)) unsigned char sh3[64];
#else
unsigned char sh0[64] __attribute__((aligned(16)));
unsigned char sh1[64] __attribute__((aligned(16)));
unsigned char sh2[64] __attribute__((aligned(16)));
unsigned char sh3[64] __attribute__((aligned(16)));
#endif
switch (type) {
case P2PKH:
{
uint32_t b0[16];
uint32_t b1[16];
uint32_t b2[16];
uint32_t b3[16];
KEYBUFFPREFIX(b0, k0, prefix);
KEYBUFFPREFIX(b1, k1, prefix);
KEYBUFFPREFIX(b2, k2, prefix);
KEYBUFFPREFIX(b3, k3, prefix);
sha256sse_1B(b0, b1, b2, b3, sh0, sh1, sh2, sh3);
ripemd160sse_32(sh0, sh1, sh2, sh3, h0, h1, h2, h3);
}
break;
case P2SH:
{
fprintf(stderr,"[E] Fixme unsopported case");
exit(0);
}
break;
}
}