using namespace gec::bigint::literal;
// Elliptic curves need to be defined before any ECC operations can be carried out. Take secp256k1 as an example, define the finite field Field for secp256k1 first.
// use uint64 x 4 to store a single element on finite field
using Bigint256 = gec::bigint::ArrayBE<uint64_t, 4>;
// define parameters required by montgomery multiplication:
// cardinality of finite field
GEC_DEF_GLOBAL(MOD, Bigint256, 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f_int);
constexpr Bigint256::LimbT MOD_P = 0xd838091dd2253531ull; // -MOD^-1 mod 2^64
GEC_DEF_GLOBAL(RR, Bigint256, 0x01000007a2000e90a1_int); // 2^512 mod MOD
GEC_DEF_GLOBAL(ONE_R, Bigint256, 0x1000003d1_int); // 2^256 mod MOD
// define the finite field type
using Field = GEC_BASE_FIELD(Bigint256, MOD, MOD_P, RR, ONE_R);
// Then define Scalar as the scalar of secp256k1.
// define parameters required by montgomery multiplication:
// cardinality of the elliptic curve
GEC_DEF_GLOBAL(CARD, Bigint256, 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141_int);
constexpr Bigint256::LimbT CARD_P = 0x4b0dff665588b13full; // -CARD^-1 mod 2^64
GEC_DEF_GLOBAL(CARD_RR, Bigint256, 0x9d671cd581c69bc5e697f5e45bcd07c6741496c20e7cf878896cf21467d7d140_int); // 2^512 mod CARD
GEC_DEF_GLOBAL(CARD_ONE_R, Bigint256, 0x14551231950b75fc4402da1732fc9bebf_int);// 2^256 mod CARD
// define the scalar type
using Scalar = GEC_BASE_FIELD(Bigint256, CARD, CARD_P, CARD_RR, CARD_ONE_R);
// Finally, define Secp256k1 as curve secp256k1.
// parameters of the elliptic curve, in montgomery form
GEC_DEF_GLOBAL(A, Field, 0); // = A * 2^256 mod MOD
GEC_DEF_GLOBAL(B, Field, 0x700001ab7_int); // = B * 2^256 mod MOD
// define the curve with Jacobian coordinate
using Secp256k1_ = GEC_CURVE(gec::curve::JacobianCurve, Field, A, B);
// use the specialized implementation for curves whose A = 0 to boost performance
using Secp256k1 = GEC_CURVE_B(gec::curve::JacobianCurve, Field, B);
// define the generator, in montgomery form
GEC_DEF_GLOBAL(GEN, Secp256k1, (
Field(0x9981e643e9089f48979f48c033fd129c231e295329bc66dbd7362e5a487e2097_int),
Field(0xcf3f851fd4a582d670b6b59aac19c1368dfc5d5d1f1dc64db15ea6d2d3dbabe2_int),
Field(0x1000003d1_int)
));
__global__ void kernel_create_eth_public_keys(eth_private_key * private_keys, eth_public_key * public_keys, uint32_t count) {
uint32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= count)
return;
// Load the private key
Scalar priv_key;
memcpy(priv_key.arr, private_keys[idx]._limbs, sizeof(eth_private_key));
// Perform elliptic curve scalar multiplication
Secp256k1 pub_key;
Secp256k1::mul(pub_key, priv_key, d_GEN);
// Store the public key
memcpy(public_keys[idx].x._limbs, pub_key.x().arr, sizeof(eth_public_key) / 2);
memcpy(public_keys[idx].y._limbs, pub_key.y().arr, sizeof(eth_public_key) / 2);
// Debug
printf("private_key: { ");
for (int i = 0; i < sizeof(priv_key.arr) / sizeof(*priv_key.arr); ++i) {
printf("%016lx, ", priv_key.arr[i]);
}
printf("}\n");
printf("public_key: { x: { ");
for (int i = 0; i < sizeof(pub_key.x().arr) / sizeof(*pub_key.x().arr); ++i) {
printf("%016lx, ", pub_key.x().arr[i]);
}
printf("}, y: { ");
for (int i = 0; i < sizeof(pub_key.y().arr) / sizeof(*pub_key.y().arr); ++i) {
printf("%016lx, ", pub_key.y().arr[i]);
}
printf("}, z: { ");
for (int i = 0; i < sizeof(pub_key.z().arr) / sizeof(*pub_key.z().arr); ++i) {
printf("%016lx, ", pub_key.z().arr[i]);
}
printf("} }\n");
}
Doing everything as in README.md:
And I'm getting the following:
For this private key, it should be
What am I doing wrong?