Well i just calculate some values for k1, k2 and the privatekey but the generated private key don't generate your publickey
k1: 0xbe404cba76f7018e965637f859560b59701ea7b2b50c3ba2d9899bc14e451032
k2: 0x7c809974edee031d2cac6ff0b2ac16b4258e727ebacfd709f340d8f5cc53df23
pvk: 0x8bfc718f4753611d61d043b499a2af787590cfb220959734c9c8c28406588ee
With any of the values k1 or k2 we can calculate the pvk with the next equation:
pvk = ( k*s - z)/r (Mod N)
Using your rsz values and my values k1 and k2, both substitutions in equation always give me the same privatekey and well this obvious the equations assume that K2 = 2 * K1 and all the subsequent substitutions come from that supposition.
I heard from other people trying to solving this example in the testnet, that they also solved some privatekey but also they doesn't generate your publickey.
For those who wanna to know how or where the numbers come from, please read
ECDSA: Elliptic Curve Signatures there are one equation, that we can use to solve some elements.
(1) : s = k
-1 * (z + r * d) (mod n)
That is the equation that generate the
s value.
d is the privatekey from that equation we can derive the private key with all the other values
s,
r,
z and
k(2) : d = ksr
-1 - zr
-1 (mod n)
We have 2 TX values (
s,
r,
z) with an unknow k, but we "know" the relationship between the two k values
(3) : k
2 = 2*K
1Since the equation (2) solve the same private key with the 2 distinct values of r,s,z and k of our transaction we can use it in the next way
(4) : k
1s
1r
1-1 - z
1r
1-1 = k
2s
2r
2-1 - z
2r
2-1 (mod n)
if we substitute (3) in (4) and and then we can solve for k
1(5) : k
1 = (z
1r
1-1 - z
2r
2-1) / (s
1r
1-1 - 2r
2-1s
2) (mod n)
Once that you have the value of k1 you can use it to solve k2 using the equation (3) and use the complete set of values r,s,z and k to solve the private key in the equation (2)
A little code in C using gmp to show this example:
/*
gcc -o k1_solver k1_solver.c -lgmp
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <gmp.h>
#include <time.h>
#include <string.h>
struct Point {
mpz_t x;
mpz_t y;
};
struct Elliptic_Curve {
mpz_t p;
mpz_t n;
};
struct Elliptic_Curve EC;
const char *EC_constant_N = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";
void calculate_pvk(mpz_t pvk,mpz_t r_inv,mpz_t s,mpz_t z,mpz_t k);
int main() {
mpz_t z1,z2,r2,r1,s1,s2,k1,k2;
mpz_t a,b,c,d,e,f,r1_inv,r2_inv,f_inv;
mpz_t pvk_calulated;
mpz_init_set_str(EC.n, EC_constant_N, 16);
/* Set the R S Z values of the first TX */
mpz_init_set_str(r1,"42c995eb98c38a8f3de7dde0f5ac63a67441a7e96b821f53931495bc6ea64cb0",16);
mpz_init_set_str(s1,"35a526e609d7022249d46d2392ff7e66b11a303d137204eb909867ae272c24b1",16);
mpz_init_set_str(z1,"c8d3c14a3b190b6ea53ce4317fdd51ca1cf1a235dffbc3ce566507061f901a5a",16);
/* Set the R S Z values of the second TX */
mpz_init_set_str(r2,"4f8bfa709c788b2ed59dd44a16e0c7b22ca7dece56d27144d418577a38b1d0d2",16);
mpz_init_set_str(s2,"096f65fa2a2c6c054b12981c42b0aece4ac861632a2900ced39070f0dd2e86e1",16);
mpz_init_set_str(z2,"57b1d4f6111f1dd7b87db91931682bad285aa2587c6239f7d3beb319ff2e0834",16);
/*Init variables GMP stuff */
mpz_init(pvk_calulated);
mpz_init(r1_inv);
mpz_init(r2_inv);
mpz_init(a);
mpz_init(b);
mpz_init(c);
mpz_init(d);
mpz_init(e);
mpz_init(f);
mpz_init(k1);
mpz_init(k2);
/*This Operations are based in the suposition that k2 = 2 * k1 mod n */
/* calcualte the r1 and r2 Invert*/
mpz_invert(r1_inv,r1,EC.n); // r1_inv = 1/r1
mpz_invert(r2_inv,r2,EC.n); // r2_inv = 1/r2
mpz_mul(a,z1,r1_inv); // a = z1 * r1_inv
mpz_mul(b,z2,r2_inv); // b = z2 * r2_inv
mpz_sub(c,a,b); // c = a - b
mpz_mul(d,r1_inv,s1); // d = r1_inv * s1
mpz_mul(e,r2_inv,s2); // e = r2_inv * s2
mpz_mul_ui(e,e,2); // e = 2 * e
mpz_sub(f,d,e); // f = d - f
mpz_invert(f_inv,f,EC.n); // f_inv = 1/f
mpz_mul(k1,f_inv,c); // k1 = f_inv * c
mpz_mod(k1,k1,EC.n); // k1 = k1 mod n
gmp_printf("k1: %Zx\n",k1);
mpz_mul_ui(k2,k1,2); // k2 = 2 * k1
mpz_mod(k2,k2,EC.n); // k2 = k2 mod n
gmp_printf("k2: %Zx\n",k2);
/* Calculate the pvk with the set of values of the first TX */
calculate_pvk(pvk_calulated,r1_inv,s1,z1,k1);
gmp_printf("pvk_calulated: %Zx\n",pvk_calulated);
/* Calculate the pvk with the set of values of the second TX */
calculate_pvk(pvk_calulated,r2_inv,s2,z2,k2);
gmp_printf("pvk_calulated: %Zx\n",pvk_calulated);
}
void calculate_pvk(mpz_t pvk,mpz_t r_inv,mpz_t s,mpz_t z,mpz_t k) {
mpz_t a,b;
mpz_init(a);
mpz_init(b);
mpz_set(a,k);
mpz_mul(a,a,s);
mpz_mul(a,a,r_inv);
mpz_set(b,r_inv);
mpz_mul(b,b,z);
mpz_sub(a,a,b);
mpz_mod(a,a,EC.n);
mpz_set(pvk,a);
mpz_clear(a);
mpz_clear(b);
}
Regards!