mirror of
https://github.com/cathugger/mkp224o.git
synced 2025-04-20 22:09:10 +00:00
prototype of trustless mining
This commit is contained in:
parent
d202229a43
commit
bd3b8d5881
5 changed files with 277 additions and 11 deletions
26
README.md
26
README.md
|
@ -3,6 +3,32 @@
|
|||
This tool generates vanity ed25519 ([hidden service version 3][v3],
|
||||
formely known as proposal 224) onion addresses.
|
||||
|
||||
### What is this fork?
|
||||
This is my shot at implementing [trustless mining](https://github.com/cathugger/mkp224o/issues/60).
|
||||
It's a garbage implementation, but it (kinda?) works.
|
||||
|
||||
#### Usage
|
||||
```
|
||||
$ ./mkp224o --genbase out/base.priv out/base.pub
|
||||
writing private base key to 'out/base.priv'
|
||||
writing public base key to 'out/base.pub'
|
||||
done.
|
||||
|
||||
$ ./mkp224o -n 1 -d out -Z --basekey out/base.pub zzz
|
||||
|
||||
$ ./mkp224o --combine out/base.priv out/zzz*.onion/hs_ed25519_secret_key
|
||||
new pk: [...]
|
||||
saving to out/zzzkzmpje34nnp2yvgz7slr7rgpajzlpihsr3rpzgmekrjosnpprf2id.onion/hs_ed25519_secret_key.fixed
|
||||
|
||||
$ cp out/zzz*.onion/hs_ed25519_secret_key.fixed /var/lib/tor/hidden_service/hs_ed25519_secret_key
|
||||
```
|
||||
|
||||
#### the ugly
|
||||
* i'm an amateur, the math might not check out
|
||||
* horrible code organization - i'm not familiar with this style of codebases at all
|
||||
* depends on ed25519-donna
|
||||
* only works with slow key generation (-Z)
|
||||
|
||||
### Requirements
|
||||
|
||||
* C99 compatible compiler (gcc and clang should work)
|
||||
|
|
200
main.c
200
main.c
|
@ -132,6 +132,13 @@ static void printhelp(FILE *out,const char *progname)
|
|||
#endif
|
||||
" --rawyaml raw (unprefixed) public/secret keys for -y/-Y\n"
|
||||
" (may be useful for tor controller API)\n"
|
||||
" --basekey base.pub\n"
|
||||
" trustless mining: the private keys found will need\n"
|
||||
" to be --combine'd with base.priv before use\n"
|
||||
" --genbase base.priv base.pub\n"
|
||||
" generate base keys for trustless mining\n"
|
||||
" --combine base.priv hs_secret_key\n"
|
||||
" combine a mined hs_secret key with a base key\n"
|
||||
" -h, --help, --usage print help to stdout and quit\n"
|
||||
" -V, --version print version information to stdout and exit\n"
|
||||
,progname,progname);
|
||||
|
@ -262,11 +269,160 @@ enum worker_type {
|
|||
WT_BATCH,
|
||||
};
|
||||
|
||||
// i'm so sorry for including an implementation header
|
||||
// i didn't find another way to get access to the functions
|
||||
#include "ed25519/ed25519_impl_pre.h"
|
||||
static void genbase(const char *privpath, const char *pubpath)
|
||||
{
|
||||
u8 base_sk[32];
|
||||
u8 base_pk[32];
|
||||
hash_512bits base_extsk;
|
||||
ge25519 ALIGN(16) A;
|
||||
bignum256modm ALIGN(16) base;
|
||||
FILE *fp;
|
||||
|
||||
randombytes(base_sk, sizeof base_sk);
|
||||
ed25519_seckey_expand(base_extsk, base_sk);
|
||||
expand256_modm(base, base_extsk, 32);
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, base);
|
||||
ge25519_pack(base_pk, &A);
|
||||
|
||||
printf("writing private base key to '%s'\n", privpath);
|
||||
fp = fopen(privpath, "w");
|
||||
if (!fp) {
|
||||
perror("couldn't open");
|
||||
exit(1);
|
||||
}
|
||||
if (fwrite(base_sk, 1, 32, fp) != 32) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
printf("writing public base key to '%s'\n", pubpath);
|
||||
fp = fopen(pubpath, "w");
|
||||
if (!fp) {
|
||||
perror("couldn't open");
|
||||
exit(1);
|
||||
}
|
||||
if (fwrite(base_pk, 1, 32, fp) != 32) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
puts("done.");
|
||||
}
|
||||
|
||||
static void combine(const char *privpath, const char *hs_secretkey)
|
||||
{
|
||||
u8 base_sk[32], secret[96];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(hs_secretkey, "r");
|
||||
if (fp == NULL) {
|
||||
perror("failed to open hs_secret_key");
|
||||
exit(1);
|
||||
}
|
||||
if (fread(secret, 1, 96, fp) != 96) {
|
||||
perror("failed to read hs_secret_key");
|
||||
exit(1);
|
||||
}
|
||||
if (memcmp(secret, "== ed25519v1-secret: type0 ==\0\0\0", 32) != 0) {
|
||||
fprintf(stderr, "invalid hs_secret_key format.\nare you sure you picked the right file?\n");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(privpath, "r");
|
||||
if (fp == NULL) {
|
||||
perror("failed to open base.priv");
|
||||
exit(1);
|
||||
}
|
||||
if (fread(base_sk, 1, sizeof base_sk, fp) != sizeof base_sk) {
|
||||
perror("failed to read base.priv");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
#if 0
|
||||
u8 pk[32];
|
||||
|
||||
hash_512bits base_extsk;
|
||||
ed25519_seckey_expand(base_extsk, base_sk);
|
||||
|
||||
bignum256modm ALIGN(16) base;
|
||||
expand256_modm(base, base_extsk, 32);
|
||||
|
||||
ge25519 ALIGN(16) A, B;
|
||||
ge25519_scalarmult_base_niels(&B, ge25519_niels_base_multiples, base);
|
||||
u8 base_pk[32];
|
||||
ge25519_pack(base_pk, &B);
|
||||
ge25519_unpack_negative_vartime(&B, base_pk);
|
||||
ge25519_pack(base_pk, &B);
|
||||
ge25519_unpack_negative_vartime(&B, base_pk);
|
||||
|
||||
bignum256modm ALIGN(16) a;
|
||||
expand256_modm(a, &secret[SKPREFIX_SIZE], 32);
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
||||
ge25519_add(&A, &A, &B);
|
||||
ge25519_pack(pk, &A);
|
||||
|
||||
printf("pk from public: ");
|
||||
for (size_t i = 0; i < sizeof(pk); i++)
|
||||
printf("%02x ", pk[i]);
|
||||
puts("");
|
||||
#endif
|
||||
|
||||
hash_512bits base_extsk;
|
||||
bignum256modm ALIGN(16) a, b;
|
||||
ge25519 ALIGN(16) A;
|
||||
u8 pk[32];
|
||||
|
||||
expand256_modm(a, &secret[32], 32);
|
||||
ed25519_seckey_expand(base_extsk, base_sk);
|
||||
expand256_modm(b, base_extsk, 32);
|
||||
|
||||
add256_modm(a, a, b);
|
||||
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
||||
ge25519_pack(pk, &A);
|
||||
|
||||
contract256_modm(&secret[32], a);
|
||||
|
||||
expand256_modm(a, &secret[32], 32);
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
||||
ge25519_pack(pk, &A);
|
||||
|
||||
printf("new pk: ");
|
||||
for (size_t i = 0; i < sizeof(pk); i++)
|
||||
printf("%02x ", pk[i]);
|
||||
puts("");
|
||||
|
||||
char *newname = malloc(strlen(hs_secretkey) + strlen(".fixed") + 1);
|
||||
strcpy(newname, hs_secretkey);
|
||||
strcat(newname, ".fixed");
|
||||
printf("saving to %s\n", newname);
|
||||
|
||||
fp = fopen(newname, "w");
|
||||
if (!fp) {
|
||||
perror("couldn't open");
|
||||
exit(1);
|
||||
}
|
||||
if (fwrite(secret, 1, sizeof secret, fp) != sizeof secret) {
|
||||
perror("failed to write fixed privkey");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
#include "ed25519/ed25519_impl_post.h"
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
const char *outfile = 0;
|
||||
const char *infile = 0;
|
||||
const char *onehostname = 0;
|
||||
const char *basekeyfile = 0;
|
||||
const char *arg;
|
||||
int ignoreargs = 0;
|
||||
int dirnameflag = 0;
|
||||
|
@ -326,6 +482,28 @@ int main(int argc,char **argv)
|
|||
printversion();
|
||||
exit(0);
|
||||
}
|
||||
else if (!strcmp(arg,"combine")) {
|
||||
if (argc != 2) {
|
||||
printhelp(stdout,progname);
|
||||
exit(0);
|
||||
}
|
||||
combine(argv[0],argv[1]);
|
||||
exit(0);
|
||||
}
|
||||
else if (!strcmp(arg,"genbase")) {
|
||||
if (argc != 2) {
|
||||
printhelp(stdout,progname);
|
||||
exit(0);
|
||||
}
|
||||
genbase(argv[0],argv[1]);
|
||||
exit(0);
|
||||
}
|
||||
else if (!strcmp(arg,"basekey")) {
|
||||
if (argc--)
|
||||
basekeyfile = *argv++;
|
||||
else
|
||||
e_additional();
|
||||
}
|
||||
else if (!strcmp(arg,"rawyaml"))
|
||||
yamlraw = 1;
|
||||
#ifdef PASSPHRASE
|
||||
|
@ -497,6 +675,28 @@ int main(int argc,char **argv)
|
|||
filters_add(arg);
|
||||
}
|
||||
|
||||
if (wt != WT_SLOW) {
|
||||
fprintf(stderr,"you're not using -Z. this will probably break.");
|
||||
}
|
||||
|
||||
if (basekeyfile) {
|
||||
u8 base_pk[32];
|
||||
FILE *fp = fopen(basekeyfile, "r");
|
||||
if (!fp) {
|
||||
perror("couldn't open basekey");
|
||||
exit(1);
|
||||
}
|
||||
if (fread(base_pk, 1, sizeof base_pk, fp) != sizeof base_pk) {
|
||||
perror("incomplete read of base_pk");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
ed25519_pubkey_setbase(base_pk);
|
||||
} else {
|
||||
fprintf(stderr, "This build requires using --basekey.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (yamlinput && yamloutput) {
|
||||
fprintf(stderr,"both -y and -Y does not make sense\n");
|
||||
exit(1);
|
||||
|
|
59
worker.c
59
worker.c
|
@ -60,6 +60,9 @@ pthread_mutex_t determseed_mutex;
|
|||
u8 determseed[SEED_LEN];
|
||||
#endif
|
||||
|
||||
static int ed25519_pubkey_onbase(u8 *pk,const u8 *sk);
|
||||
static void sanitycheck(const u8 *sk, const u8 *pk);
|
||||
|
||||
|
||||
char *makesname(void)
|
||||
{
|
||||
|
@ -88,16 +91,7 @@ static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
|||
pthread_mutex_unlock(&keysgenerated_mutex);
|
||||
}
|
||||
|
||||
// disabled as this was never ever triggered as far as I'm aware
|
||||
#if 0
|
||||
// Sanity check that the public key matches the private one.
|
||||
ge_p3 ALIGN(16) point;
|
||||
u8 testpk[PUBLIC_LEN];
|
||||
ge_scalarmult_base(&point,&secret[SKPREFIX_SIZE]);
|
||||
ge_p3_tobytes(testpk,&point);
|
||||
if (memcmp(testpk,&pubonion[PKPREFIX_SIZE],PUBLIC_LEN) != 0)
|
||||
abort();
|
||||
#endif
|
||||
sanitycheck(&secret[SKPREFIX_SIZE], &pubonion[PKPREFIX_SIZE]);
|
||||
|
||||
if (!yamloutput) {
|
||||
if (createdir(sname,1) != 0) {
|
||||
|
@ -266,3 +260,48 @@ void worker_init(void)
|
|||
crypto_sign_ed25519_donna_ge_initeightpoint();
|
||||
#endif
|
||||
}
|
||||
|
||||
// there's not really any good place to add ed25519 functions
|
||||
// so i just add them there
|
||||
// i don't understand how this codebase is organized :(
|
||||
|
||||
ge25519 ALIGN(16) PUBKEY_BASE = {0};
|
||||
int pubkey_base_initialized;
|
||||
|
||||
void ed25519_pubkey_setbase(const u8 base_pk[32])
|
||||
{
|
||||
u8 tmp_pk[32];
|
||||
ge25519_unpack_negative_vartime(&PUBKEY_BASE, base_pk);
|
||||
// dumb hack: unpack flips the point. to get the original point
|
||||
// back, i just pack and unpack it again
|
||||
ge25519_pack(tmp_pk, &PUBKEY_BASE);
|
||||
ge25519_unpack_negative_vartime(&PUBKEY_BASE, tmp_pk);
|
||||
pubkey_base_initialized = 1;
|
||||
}
|
||||
|
||||
static int ed25519_pubkey_onbase(u8 *pk,const u8 *sk)
|
||||
{
|
||||
bignum256modm a;
|
||||
ge25519 ALIGN(16) A;
|
||||
|
||||
if (unlikely(pubkey_base_initialized == 0))
|
||||
abort();
|
||||
|
||||
// ge_scalarmult_base(&A, sk);
|
||||
expand256_modm(a,sk,32);
|
||||
ge25519_scalarmult_base_niels(&A,ge25519_niels_base_multiples,a);
|
||||
ge25519_add(&A, &A, &PUBKEY_BASE);
|
||||
ge25519_pack(pk,&A);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void sanitycheck(const u8 *sk, const u8 *pk) {
|
||||
u8 testpk[PUBLIC_LEN];
|
||||
ed25519_pubkey_onbase(testpk, sk);
|
||||
if (memcmp(testpk,pk,PUBLIC_LEN) != 0) {
|
||||
fprintf(stderr, "Sanity check failed. Either I fucked something up, or you're using an unsupported combination of options. Probably both.\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
|
1
worker.h
1
worker.h
|
@ -36,6 +36,7 @@ extern u8 determseed[SEED_LEN];
|
|||
#endif
|
||||
|
||||
extern void worker_init(void);
|
||||
extern void ed25519_pubkey_setbase(const u8 base_pk[32]);
|
||||
|
||||
extern char *makesname(void);
|
||||
extern size_t worker_batch_memuse(void);
|
||||
|
|
|
@ -42,7 +42,7 @@ again:
|
|||
if (unlikely(endwork))
|
||||
goto end;
|
||||
|
||||
ed25519_pubkey(pk,sk);
|
||||
ed25519_pubkey_onbase(pk,sk);
|
||||
|
||||
#ifdef STATISTICS
|
||||
++st->numcalc.v;
|
||||
|
|
Loading…
Add table
Reference in a new issue