contribute decently fast yggdrasil address generator in C

This commit is contained in:
fifteenthcommotion 2019-05-11 16:31:46 -07:00
parent c11f08f2a3
commit 5a3c730097
8 changed files with 318 additions and 0 deletions

View File

@ -0,0 +1,7 @@
*
!.gitignore
!Makefile
!README.md
!LICENSE
!*.c
!*.h

View File

@ -0,0 +1 @@
As public domain as possible. Don't blame me if your computer explodes.

View File

@ -0,0 +1,12 @@
.PHONY: all
all: util yggdrasil-brute-multi-curve25519 yggdrasil-brute-multi-ed25519
util: util.c
gcc -Wall -std=c89 -O3 -c -o util.o util.c
yggdrasil-brute-multi-ed25519: yggdrasil-brute-multi-ed25519.c util.o
gcc -Wall -std=c89 -O3 -o yggdrasil-brute-multi-ed25519 -lsodium yggdrasil-brute-multi-ed25519.c util.o
yggdrasil-brute-multi-curve25519: yggdrasil-brute-multi-curve25519.c util.o
gcc -Wall -std=c89 -O3 -o yggdrasil-brute-multi-curve25519 -lsodium yggdrasil-brute-multi-curve25519.c util.o

View File

@ -0,0 +1,8 @@
# yggdrasil-brute-simple
Simple program for finding curve25519 and ed25519 public keys whose sha512 hash has many leading ones.
Because ed25519 private keys consist of a seed that is hashed to find the secret part of the keypair,
this program is near optimal for finding ed25519 keypairs. Curve25519 key generation, on the other hand,
could be further optimized with elliptic curve magic.
Depends on libsodium.

View File

@ -0,0 +1,62 @@
#include "yggdrasil-brute.h"
int find_where(unsigned char hash[64], unsigned char besthashlist[NUMKEYS][64]) {
/* Where to insert hash into sorted hashlist */
int j;
int where = -1;
for (j = 0; j < NUMKEYS; ++j) {
if (memcmp(hash, besthashlist[j], 64) > 0) ++where;
else break;
}
return where;
}
void insert_64(unsigned char itemlist[NUMKEYS][64], unsigned char item[64], int where) {
int j;
for (j = 0; j < where; ++j) {
memcpy(itemlist[j], itemlist[j+1], 64);
}
memcpy(itemlist[where], item, 64);
}
void insert_32(unsigned char itemlist[NUMKEYS][32], unsigned char item[32], int where) {
int j;
for (j = 0; j < where; ++j) {
memcpy(itemlist[j], itemlist[j+1], 32);
}
memcpy(itemlist[where], item, 32);
}
void make_addr(unsigned char addr[32], unsigned char hash[64]) {
/* Public key hash to yggdrasil ipv6 address */
int i;
int offset;
unsigned char mask;
unsigned char c;
int ones = 0;
unsigned char br = 0; /* false */
for (i = 0; i < 64 && !br; ++i) {
mask = 128;
c = hash[i];
while (mask) {
if (c & mask) {
++ones;
} else {
br = 1; /* true */
break;
}
mask >>= 1;
}
}
addr[0] = 2;
addr[1] = ones;
offset = ones + 1;
for (i = 0; i < 14; ++i) {
c = hash[offset/8] << (offset%8);
c |= hash[offset/8 + 1] >> (8 - offset%8);
addr[i + 2] = c;
offset += 8;
}
}

View File

@ -0,0 +1,107 @@
/*
sk: 32 random bytes
sk[0] &= 248;
sk[31] &= 127;
sk[31] |= 64;
increment sk
pk = curve25519_scalarmult_base(mysecret)
hash = sha512(pk)
if besthash:
bestsk = sk
besthash = hash
*/
#include "yggdrasil-brute.h"
void seed(unsigned char sk[32]) {
randombytes_buf(sk, 32);
sk[0] &= 248;
sk[31] &= 127;
sk[31] |= 64;
}
int main(int argc, char **argv) {
int i;
int j;
unsigned char addr[16];
time_t starttime;
time_t requestedtime;
unsigned char bestsklist[NUMKEYS][32];
unsigned char bestpklist[NUMKEYS][32];
unsigned char besthashlist[NUMKEYS][64];
unsigned char sk[32];
unsigned char pk[32];
unsigned char hash[64];
unsigned int runs = 0;
int where;
if (argc != 2) {
fprintf(stderr, "usage: ./yggdrasil-brute-multi-curve25519 <seconds>\n");
return 1;
}
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
printf("sodium init failed!\n");
return 1;
}
starttime = time(NULL);
requestedtime = atoi(argv[1]);
if (requestedtime < 0) requestedtime = 0;
fprintf(stderr, "Searching for yggdrasil curve25519 keys (this will take slightly longer than %ld seconds)\n", requestedtime);
sodium_memzero(bestsklist, NUMKEYS * 32);
sodium_memzero(bestpklist, NUMKEYS * 32);
sodium_memzero(besthashlist, NUMKEYS * 64);
seed(sk);
do {
/* generate pubkey, hash, compare, increment secret.
* this loop should take 4 seconds on modern hardware */
for (i = 0; i < (1 << 16); ++i) {
++runs;
if (crypto_scalarmult_curve25519_base(pk, sk) != 0) {
printf("scalarmult to create pub failed!\n");
return 1;
}
crypto_hash_sha512(hash, pk, 32);
where = find_where(hash, besthashlist);
if (where >= 0) {
insert_32(bestsklist, sk, where);
insert_32(bestpklist, pk, where);
insert_64(besthashlist, hash, where);
seed(sk);
}
for (j = 1; j < 31; ++j) if (++sk[j]) break;
}
} while (time(NULL) - starttime < requestedtime || runs < NUMKEYS);
fprintf(stderr, "--------------addr-------------- -----------------------------secret----------------------------- -----------------------------public-----------------------------\n");
for (i = 0; i < NUMKEYS; ++i) {
make_addr(addr, besthashlist[i]);
for (j = 0; j < 16; ++j) printf("%02x", addr[j]);
printf(" ");
for (j = 0; j < 32; ++j) printf("%02x", bestsklist[i][j]);
printf(" ");
for (j = 0; j < 32; ++j) printf("%02x", bestpklist[i][j]);
printf("\n");
}
sodium_memzero(bestsklist, NUMKEYS * 32);
sodium_memzero(sk, 32);
return 0;
}

View File

@ -0,0 +1,109 @@
/*
seed: 32 random bytes
sk: sha512(seed)
sk[0] &= 248
sk[31] &= 127
sk[31] |= 64
pk: scalarmult_ed25519_base(sk)
increment seed
generate sk
generate pk
hash = sha512(mypub)
if besthash:
bestseed = seed
bestseckey = sk
bestpubkey = pk
besthash = hash
*/
#include "yggdrasil-brute.h"
int main(int argc, char **argv) {
int i;
int j;
time_t starttime;
time_t requestedtime;
unsigned char bestsklist[NUMKEYS][64]; /* sk contains pk */
unsigned char besthashlist[NUMKEYS][64];
unsigned char seed[32];
unsigned char sk[64];
unsigned char pk[32];
unsigned char hash[64];
unsigned int runs = 0;
int where;
if (argc != 2) {
fprintf(stderr, "usage: ./yggdrasil-brute-multi-curve25519 <seconds>\n");
return 1;
}
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
printf("sodium init failed!\n");
return 1;
}
starttime = time(NULL);
requestedtime = atoi(argv[1]);
if (requestedtime < 0) requestedtime = 0;
fprintf(stderr, "Searching for yggdrasil ed25519 keys (this will take slightly longer than %ld seconds)\n", requestedtime);
sodium_memzero(bestsklist, NUMKEYS * 64);
sodium_memzero(besthashlist, NUMKEYS * 64);
randombytes_buf(seed, 32);
do {
/* generate pubkey, hash, compare, increment secret.
* this loop should take 4 seconds on modern hardware */
for (i = 0; i < (1 << 17); ++i) {
++runs;
crypto_hash_sha512(sk, seed, 32);
if (crypto_scalarmult_ed25519_base(pk, sk) != 0) {
printf("scalarmult to create pub failed!\n");
return 1;
}
memcpy(sk + 32, pk, 32);
crypto_hash_sha512(hash, pk, 32);
/* insert into local list of good key */
where = find_where(hash, besthashlist);
if (where >= 0) {
insert_64(bestsklist, sk, where);
insert_64(besthashlist, hash, where);
randombytes_buf(seed, 32);
}
for (j = 1; j < 31; ++j) if (++seed[j]) break;
}
} while (time(NULL) - starttime < requestedtime || runs < NUMKEYS);
fprintf(stderr, "!! Secret key is seed concatenated with public !!\n");
fprintf(stderr, "---hash--- ------------------------------seed------------------------------ -----------------------------public-----------------------------\n");
for (i = 0; i < NUMKEYS; ++i) {
for (j = 0; j < 5; ++j) printf("%02x", besthashlist[i][j]);
printf(" ");
for (j = 0; j < 32; ++j) printf("%02x", bestsklist[i][j]);
printf(" ");
for (j = 32; j < 64; ++j) printf("%02x", bestsklist[i][j]);
printf("\n");
}
sodium_memzero(bestsklist, NUMKEYS * 64);
sodium_memzero(sk, 64);
sodium_memzero(seed, 32);
return 0;
}

View File

@ -0,0 +1,12 @@
#include <sodium.h>
#include <stdio.h> /* printf */
#include <string.h> /* memcpy */
#include <stdlib.h> /* atoi */
#include <time.h> /* time */
#define NUMKEYS 10
void make_addr(unsigned char addr[32], unsigned char hash[64]);
int find_where(unsigned char hash[64], unsigned char besthashlist[NUMKEYS][64]);
void insert_64(unsigned char itemlist[NUMKEYS][64], unsigned char item[64], int where);
void insert_32(unsigned char itemlist[NUMKEYS][32], unsigned char item[32], int where);