mirror of
https://github.com/cathugger/mkp224o.git
synced 2025-01-09 11:07:19 -03:00
optional functionality for writing results to the single file and extracting specific keys from it
This commit is contained in:
parent
37a1506b18
commit
6a416795b7
7 changed files with 554 additions and 47 deletions
16
Makefile.in
16
Makefile.in
|
@ -26,10 +26,17 @@ MAINOBJ= \
|
|||
cpucount.c.o \
|
||||
base32_to.c.o \
|
||||
base32_from.c.o \
|
||||
base64_to.c.o \
|
||||
base64_from.c.o \
|
||||
ioutil.c.o \
|
||||
$(ED25519OBJ) \
|
||||
keccak.c.o
|
||||
|
||||
TEST_BASE64OBJ= \
|
||||
test_base64.c.o \
|
||||
base64_to.c.o \
|
||||
base64_from.c.o
|
||||
|
||||
TEST_BASE32OBJ= \
|
||||
test_base32.c.o \
|
||||
base32_to.c.o \
|
||||
|
@ -48,6 +55,7 @@ TEST_ED25519OBJ= \
|
|||
|
||||
ALLO= $(sort \
|
||||
$(MAINOBJ) \
|
||||
$(TEST_BASE64OBJ) \
|
||||
$(TEST_BASE32OBJ) \
|
||||
$(TEST_BASE16OBJ) \
|
||||
$(TEST_ED25519OBJ) \
|
||||
|
@ -60,7 +68,7 @@ CLEANO= $(filter %.o,$(ALLO))
|
|||
MAINLIB= -lpthread -lsodium @MAINLIB@
|
||||
TEST_ED25519LIB= -lsodium
|
||||
|
||||
EXE= mkp224o test_base32 test_base16 test_ed25519
|
||||
EXE= mkp224o test_base64 test_base32 test_base16 test_ed25519
|
||||
|
||||
default: mkp224o
|
||||
|
||||
|
@ -69,6 +77,9 @@ all: $(EXE)
|
|||
mkp224o: $(MAINOBJ)
|
||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@.tmp $^ $(MAINLIB) && $(MV) $@.tmp $@
|
||||
|
||||
test_base64: $(TEST_BASE64OBJ)
|
||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@.tmp $^ && $(MV) $@.tmp $@
|
||||
|
||||
test_base32: $(TEST_BASE32OBJ)
|
||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@.tmp $^ && $(MV) $@.tmp $@
|
||||
|
||||
|
@ -104,6 +115,8 @@ base16_from.c.o: types.h base16.h
|
|||
base16_to.c.o: types.h base16.h
|
||||
base32_from.c.o: types.h base32.h
|
||||
base32_to.c.o: types.h base32.h
|
||||
base64_from.c.o: types.h base64.h
|
||||
base64_to.c.o: types.h base64.h
|
||||
cpucount.c.o: cpucount.h
|
||||
ed25519/amd64-51-30k/batch.c.o: ed25519/amd64-51-30k/crypto_sign.h
|
||||
ed25519/amd64-51-30k/batch.c.o: ed25519/amd64-51-30k/ed25519.h
|
||||
|
@ -384,6 +397,7 @@ main.c.o: ed25519/ed25519-donna/ed25519-donna-64bit-x86.h
|
|||
main.c.o: ed25519/ed25519-donna/ed25519-donna-impl-base.h ioutil.h filters.h
|
||||
test_base16.c.o: types.h base16.h
|
||||
test_base32.c.o: types.h base32.h
|
||||
test_base64.c.o: types.h base64.h
|
||||
test_ed25519.c.o: types.h base16.h ed25519/ed25519.h ed25519/ref10/ed25519.h
|
||||
test_ed25519.c.o: ed25519/ref10/ge.h ed25519/ref10/fe.h
|
||||
test_ed25519.c.o: ed25519/ref10/crypto_int32.h ed25519/amd64-51-30k/ed25519.h
|
||||
|
|
11
base64.h
Normal file
11
base64.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
// converts src[0:slen] to base64 string
|
||||
char *base64_to(char *dst,const u8 *src,size_t slen);
|
||||
// calculates length needed to store data converted to base64
|
||||
#define BASE64_TO_LEN(l) (((l + 3 - 1) / 3) * 4)
|
||||
// converts src string from base64
|
||||
size_t base64_from(u8 *dst,const char *src,size_t slen);
|
||||
// calculates length needed to store data converted from base
|
||||
#define BASE64_FROM_LEN(l) ((l) / 4 * 3)
|
||||
// validates base32 string and optionally stores length of valid data
|
||||
// returns 1 if whole string is good, 0 if string contains invalid data
|
||||
int base64_valid(const char *src,size_t *count);
|
90
base64_from.c
Normal file
90
base64_from.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "types.h"
|
||||
#include "base64.h"
|
||||
|
||||
static const u8 base64f[256] = {
|
||||
//00 01 02 03 04 05 06 07
|
||||
//08 09 0A 0B 0C 0D 0E 0F
|
||||
// 0x00..0x3F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x08
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x18
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x20
|
||||
0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, // 0x28
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30
|
||||
0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x38
|
||||
// 0x40..0x7F
|
||||
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40
|
||||
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48
|
||||
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50
|
||||
0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x58
|
||||
0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68
|
||||
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70
|
||||
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x78
|
||||
// 0x80..0xBF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
// 0xC0..0xFF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
size_t base64_from(u8 *dst,const char *src,size_t srclen)
|
||||
{
|
||||
if (srclen % 4) {
|
||||
return -1;
|
||||
} else if (!srclen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t dstlen = BASE64_FROM_LEN(srclen);
|
||||
dstlen -= (src[srclen - 1] == '=');
|
||||
dstlen -= (src[srclen - 2] == '=');
|
||||
|
||||
for (size_t i = 0, j = 0; i < srclen;) {
|
||||
u32 sixbits[4];
|
||||
|
||||
sixbits[0] = base64f[(unsigned char)src[i++]];
|
||||
sixbits[1] = base64f[(unsigned char)src[i++]];
|
||||
sixbits[2] = (src[i] == '=' ? (0 & i++) : base64f[(unsigned char)src[i++]]);
|
||||
sixbits[3] = (src[i] == '=' ? (0 & i++) : base64f[(unsigned char)src[i++]]);
|
||||
|
||||
u32 threebytes = 0
|
||||
| (sixbits[0] << (3 * 6))
|
||||
| (sixbits[1] << (2 * 6))
|
||||
| (sixbits[2] << (1 * 6))
|
||||
| (sixbits[3] << (0 * 6));
|
||||
|
||||
if (j < dstlen) dst[j++] = (threebytes >> (2 * 8));
|
||||
if (j < dstlen) dst[j++] = (threebytes >> (1 * 8)) & 0xff;
|
||||
if (j < dstlen) dst[j++] = (threebytes >> (0 * 8)) & 0xff;
|
||||
}
|
||||
return dstlen;
|
||||
}
|
||||
|
||||
int base64_valid(const char *src,size_t *count)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = src;base64f[(u8)*p] != 0xFF;++p)
|
||||
;
|
||||
|
||||
if (count)
|
||||
*count = (size_t) (p - src);
|
||||
return !*p;
|
||||
}
|
51
base64_to.c
Normal file
51
base64_to.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "types.h"
|
||||
#include "base64.h"
|
||||
|
||||
static const char base64t[64] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/',
|
||||
};
|
||||
|
||||
char *base64_to(char *dst,const u8 *src,size_t slen)
|
||||
{
|
||||
if (!slen) {
|
||||
*dst = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < slen;) {
|
||||
u32 threebytes = 0;
|
||||
threebytes |= (i < slen ? (unsigned char)src[i++] : (unsigned char)0) << (2 * 8);
|
||||
threebytes |= (i < slen ? (unsigned char)src[i++] : (unsigned char)0) << (1 * 8);
|
||||
threebytes |= (i < slen ? (unsigned char)src[i++] : (unsigned char)0) << (0 * 8);
|
||||
|
||||
*dst++ = base64t[(threebytes >> (3 * 6)) & 63];
|
||||
*dst++ = base64t[(threebytes >> (2 * 6)) & 63];
|
||||
*dst++ = base64t[(threebytes >> (1 * 6)) & 63];
|
||||
*dst++ = base64t[(threebytes >> (0 * 6)) & 63];
|
||||
}
|
||||
|
||||
switch (slen % 3) {
|
||||
case 0 : break;
|
||||
case 1 : {
|
||||
*(dst-2) = '=';
|
||||
*(dst-1) = '=';
|
||||
break;
|
||||
}
|
||||
case 2 : {
|
||||
*(dst-1) = '=';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
return dst;
|
||||
}
|
41
constants.h
Normal file
41
constants.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
#define LINEFEED_LEN (sizeof(char))
|
||||
#define NULLTERM_LEN (sizeof(char))
|
||||
#define PATH_SEPARATOR_LEN (sizeof(char))
|
||||
|
||||
static const int use_secret_mode = 1;
|
||||
static const int use_public_mode = 0;
|
||||
|
||||
static const char hostname_filename[] = "hostname";
|
||||
static const char secret_key_filename[] = "hs_ed25519_secret_key";
|
||||
static const char public_key_filename[] = "hs_ed25519_public_key";
|
||||
|
||||
static const char keys_field_generated[] = "generated:";
|
||||
static const char keys_field_hostname[] = " - hostname: ";
|
||||
static const char keys_field_secretkey[] = " - hs_ed25519_secret_key: ";
|
||||
static const char keys_field_publickey[] = " - hs_ed25519_public_key: ";
|
||||
static const char keys_field_time[] = " - time: ";
|
||||
|
||||
#define KEYS_FIELD_GENERATED_LEN (sizeof(keys_field_generated) - NULLTERM_LEN)
|
||||
#define KEYS_FIELD_HOSTNAME_LEN (sizeof(keys_field_hostname) - NULLTERM_LEN)
|
||||
#define KEYS_FIELD_SECRETKEY_LEN (sizeof(keys_field_secretkey) - NULLTERM_LEN)
|
||||
#define KEYS_FIELD_PUBLICKEY_LEN (sizeof(keys_field_publickey) - NULLTERM_LEN)
|
||||
#define KEYS_FIELD_TIME_LEN (sizeof(keys_field_time) - NULLTERM_LEN)
|
||||
|
||||
static const char hostname_example[] = "xxxxxvsjzke274nisktdqcl3eqm5ve3m6iur6vwme7m5p6kxivrvjnyd.onion";
|
||||
static const char seckey_example[] = "PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACwCPMr6rvBRtkW7ZzZ8P7Ne4acRZrhPrN/EF6AETRraFGvdrkW5es4WXB2UxrbuUf8zPoIKkXK5cpdakYdUeM3";
|
||||
static const char pubkey_example[] = "PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAAC973vWScqJr/GokqY4CXskGdqTbPIpH1bMJ9nX+VdFYw==";
|
||||
static const char time_example[] = "2018-07-04 21:31:20";
|
||||
|
||||
#define HOSTNAME_LEN (sizeof(hostname_example) - NULLTERM_LEN)
|
||||
#define SECKEY_LEN (sizeof(seckey_example) - NULLTERM_LEN)
|
||||
#define PUBKEY_LEN (sizeof(pubkey_example) - NULLTERM_LEN)
|
||||
#define TIME_LEN (sizeof(time_example) - NULLTERM_LEN)
|
||||
|
||||
#define KEYS_LEN ( KEYS_FIELD_GENERATED_LEN + LINEFEED_LEN \
|
||||
+ KEYS_FIELD_HOSTNAME_LEN + HOSTNAME_LEN + LINEFEED_LEN \
|
||||
+ KEYS_FIELD_SECRETKEY_LEN + SECKEY_LEN + LINEFEED_LEN \
|
||||
+ KEYS_FIELD_PUBLICKEY_LEN + PUBKEY_LEN + LINEFEED_LEN \
|
||||
+ KEYS_FIELD_TIME_LEN + TIME_LEN + LINEFEED_LEN \
|
||||
+ LINEFEED_LEN \
|
||||
)
|
340
main.c
340
main.c
|
@ -2,6 +2,7 @@
|
|||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -16,10 +17,12 @@
|
|||
#include "likely.h"
|
||||
#include "vec.h"
|
||||
#include "base32.h"
|
||||
#include "base64.h"
|
||||
#include "cpucount.h"
|
||||
#include "keccak.h"
|
||||
#include "ed25519/ed25519.h"
|
||||
#include "ioutil.h"
|
||||
#include "constants.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define FSZ "%zu"
|
||||
|
@ -28,12 +31,12 @@
|
|||
#endif
|
||||
|
||||
// additional 0 terminator is added by C
|
||||
static const char * const pkprefix = "== ed25519v1-public: type0 ==\0\0";
|
||||
#define pkprefixlen (29 + 3)
|
||||
static const char * const skprefix = "== ed25519v1-secret: type0 ==\0\0";
|
||||
#define skprefixlen (29 + 3)
|
||||
static const char * const checksumstr = ".onion checksum";
|
||||
#define checksumstrlen 15
|
||||
static const char pkprefix[] = "== ed25519v1-public: type0 ==\0\0";
|
||||
#define pkprefixlen (sizeof(pkprefix)) // three null-terminators included
|
||||
static const char skprefix[] = "== ed25519v1-secret: type0 ==\0\0";
|
||||
#define skprefixlen (sizeof(skprefix)) // three null-terminators included
|
||||
static const char checksumstr[] = ".onion checksum";
|
||||
#define checksumstrlen (sizeof(checksumstr) - NULLTERM_LEN)
|
||||
|
||||
// output directory
|
||||
static char *workdir = 0;
|
||||
|
@ -49,7 +52,10 @@ static int quietflag = 0;
|
|||
// with checksum + version num
|
||||
#define PUBONION_LEN (PUBLIC_LEN + 3)
|
||||
// with newline included
|
||||
#define ONIONLEN 62
|
||||
#define ONION_LEN 62
|
||||
|
||||
#define FORMATTED_SECRET_LEN (skprefixlen + SECRET_LEN)
|
||||
#define FORMATTED_PUBLIC_LEN (pkprefixlen + PUBLIC_LEN)
|
||||
|
||||
static size_t onionendpos; // end of .onion within string
|
||||
static size_t direndpos; // end of dir before .onion within string
|
||||
|
@ -58,6 +64,7 @@ static size_t printlen; // precalculated, related to printstartpos
|
|||
|
||||
static pthread_mutex_t fout_mutex;
|
||||
static FILE *fout;
|
||||
const char *outfilekeys = 0;
|
||||
static size_t numneedgenerate = 0;
|
||||
static int numwords = 1;
|
||||
static pthread_mutex_t keysgenerated_mutex;
|
||||
|
@ -111,6 +118,80 @@ struct tstatstruct {
|
|||
VEC_STRUCT(tstatsvec,struct tstatstruct);
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
u8 raw[pkprefixlen + PUBLIC_LEN + 32];
|
||||
struct {
|
||||
u64 prefix[4];
|
||||
u64 key[4];
|
||||
u64 hash[4];
|
||||
} i;
|
||||
} pubonionunion;
|
||||
|
||||
|
||||
|
||||
#define BUF_APPEND(buf,offset,src,srclen) strncpy(&buf[offset],src,srclen); offset += srclen;
|
||||
#define BUF_APPEND_CSTR(buf,offset,src) BUF_APPEND(buf,offset,src,strlen(src))
|
||||
#define BUF_APPEND_CHAR(buf,offet,c) buf[offset++] = c;
|
||||
|
||||
static void writekeys(const char *hostname, const u8 *formated_secret, const u8 *formated_public)
|
||||
{
|
||||
char keysbuf[KEYS_LEN];
|
||||
size_t offset = 0;
|
||||
|
||||
BUF_APPEND_CSTR(keysbuf, offset, keys_field_generated);
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
BUF_APPEND_CSTR(keysbuf, offset, keys_field_hostname);
|
||||
BUF_APPEND(keysbuf, offset, hostname, ONION_LEN);
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
BUF_APPEND_CSTR(keysbuf, offset, keys_field_secretkey);
|
||||
char seckeybuf[SECKEY_LEN + NULLTERM_LEN];
|
||||
base64_to(seckeybuf, formated_secret, FORMATTED_SECRET_LEN);
|
||||
BUF_APPEND(keysbuf, offset, seckeybuf, SECKEY_LEN);
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
BUF_APPEND_CSTR(keysbuf, offset, keys_field_publickey);
|
||||
char pubkeybuf[PUBKEY_LEN + NULLTERM_LEN];
|
||||
base64_to(pubkeybuf, formated_public, FORMATTED_PUBLIC_LEN);
|
||||
BUF_APPEND(keysbuf, offset, pubkeybuf, PUBKEY_LEN);
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
BUF_APPEND_CSTR(keysbuf, offset, keys_field_time);
|
||||
char timebuf[TIME_LEN + NULLTERM_LEN];
|
||||
time_t timer;
|
||||
struct tm* tm_info;
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
strftime(timebuf, TIME_LEN + NULLTERM_LEN, "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
BUF_APPEND(keysbuf, offset, timebuf, TIME_LEN);
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
BUF_APPEND_CHAR(keysbuf, offset, '\n');
|
||||
|
||||
assert(offset == KEYS_LEN);
|
||||
|
||||
pthread_mutex_lock(&fout_mutex);
|
||||
fwrite(keysbuf,sizeof(keysbuf),1,fout);
|
||||
fflush(fout);
|
||||
pthread_mutex_unlock(&fout_mutex);
|
||||
}
|
||||
|
||||
#undef BUF_APPEND_CHAR
|
||||
#undef BUF_APPEND_CSTR
|
||||
#undef BUF_APPEND
|
||||
|
||||
static void printhostname(const char *hostname)
|
||||
{
|
||||
char buf[ONION_LEN + LINEFEED_LEN];
|
||||
strncpy(buf,hostname,ONION_LEN);
|
||||
buf[ONION_LEN] = '\n';
|
||||
|
||||
pthread_mutex_lock(&fout_mutex);
|
||||
fwrite(buf,sizeof(buf),1,fout);
|
||||
fflush(fout);
|
||||
pthread_mutex_unlock(&fout_mutex);
|
||||
}
|
||||
|
||||
static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
||||
{
|
||||
|
@ -125,12 +206,6 @@ static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
|||
}
|
||||
}
|
||||
|
||||
if (createdir(sname,1) != 0) {
|
||||
if (numneedgenerate)
|
||||
pthread_mutex_unlock(&keysgenerated_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (numneedgenerate) {
|
||||
++keysgenerated;
|
||||
if (keysgenerated >= numneedgenerate)
|
||||
|
@ -138,6 +213,21 @@ static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
|||
pthread_mutex_unlock(&keysgenerated_mutex);
|
||||
}
|
||||
|
||||
if (fout) {
|
||||
if (outfilekeys) {
|
||||
writekeys(&sname[printstartpos],secret,pubonion);
|
||||
return;
|
||||
} else {
|
||||
printhostname(&sname[printstartpos]);
|
||||
}
|
||||
}
|
||||
|
||||
if (createdir(sname,1) != 0) {
|
||||
if (numneedgenerate)
|
||||
pthread_mutex_unlock(&keysgenerated_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(&sname[onionendpos],"/hs_ed25519_secret_key");
|
||||
writetofile(sname,secret,skprefixlen + SECRET_LEN,1);
|
||||
|
||||
|
@ -145,20 +235,13 @@ static void onionready(char *sname,const u8 *secret,const u8 *pubonion)
|
|||
FILE *hfile = fopen(sname,"w");
|
||||
if (hfile) {
|
||||
sname[onionendpos] = '\n';
|
||||
fwrite(&sname[direndpos],ONIONLEN + 1,1,hfile);
|
||||
fwrite(&sname[direndpos],ONION_LEN + 1,1,hfile);
|
||||
fclose(hfile);
|
||||
}
|
||||
|
||||
strcpy(&sname[onionendpos],"/hs_ed25519_public_key");
|
||||
writetofile(sname,pubonion,pkprefixlen + PUBLIC_LEN,0);
|
||||
|
||||
if (fout) {
|
||||
sname[onionendpos] = '\n';
|
||||
pthread_mutex_lock(&fout_mutex);
|
||||
fwrite(&sname[printstartpos],printlen,1,fout);
|
||||
fflush(fout);
|
||||
pthread_mutex_unlock(&fout_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
// little endian inc
|
||||
|
@ -188,14 +271,7 @@ static inline void shiftpk(u8 *dst,const u8 *src,size_t sbits)
|
|||
|
||||
static void *dowork(void *task)
|
||||
{
|
||||
union pubonionunion {
|
||||
u8 raw[pkprefixlen + PUBLIC_LEN + 32];
|
||||
struct {
|
||||
u64 prefix[4];
|
||||
u64 key[4];
|
||||
u64 hash[4];
|
||||
} i;
|
||||
} pubonion;
|
||||
pubonionunion pubonion;
|
||||
u8 * const pk = &pubonion.raw[pkprefixlen];
|
||||
u8 secret[skprefixlen + SECRET_LEN];
|
||||
u8 * const sk = &secret[skprefixlen];
|
||||
|
@ -217,7 +293,7 @@ static void *dowork(void *task)
|
|||
memcpy(hashsrc,checksumstr,checksumstrlen);
|
||||
hashsrc[checksumstrlen + PUBLIC_LEN] = 0x03; // version
|
||||
|
||||
sname = (char *) malloc(workdirlen + ONIONLEN + 63 + 1);
|
||||
sname = (char *) malloc(workdirlen + ONION_LEN + 63 + 1);
|
||||
if (!sname)
|
||||
abort();
|
||||
if (workdir)
|
||||
|
@ -295,14 +371,7 @@ static void addsztoscalar32(u8 *dst,size_t v)
|
|||
|
||||
static void *dofastwork(void *task)
|
||||
{
|
||||
union pubonionunion {
|
||||
u8 raw[pkprefixlen + PUBLIC_LEN + 32];
|
||||
struct {
|
||||
u64 prefix[4];
|
||||
u64 key[4];
|
||||
u64 hash[4];
|
||||
} i;
|
||||
} pubonion;
|
||||
pubonionunion pubonion;
|
||||
u8 * const pk = &pubonion.raw[pkprefixlen];
|
||||
u8 secret[skprefixlen + SECRET_LEN];
|
||||
u8 * const sk = &secret[skprefixlen];
|
||||
|
@ -326,7 +395,7 @@ static void *dofastwork(void *task)
|
|||
memcpy(hashsrc,checksumstr,checksumstrlen);
|
||||
hashsrc[checksumstrlen + PUBLIC_LEN] = 0x03; // version
|
||||
|
||||
sname = (char *) malloc(workdirlen + ONIONLEN + 63 + 1);
|
||||
sname = (char *) malloc(workdirlen + ONION_LEN + 63 + 1);
|
||||
if (!sname)
|
||||
abort();
|
||||
if (workdir)
|
||||
|
@ -411,6 +480,8 @@ static void printhelp(FILE *out,const char *progname)
|
|||
"\t-q - do not print diagnostic output to stderr\n"
|
||||
"\t-x - do not print onion names\n"
|
||||
"\t-o filename - output onion names to specified file\n"
|
||||
"\t-O filename - output onion names with base64 encoded keys to specified file\n"
|
||||
"\t-i filename host.onion - read file with keys and create directory with keys for specified host\n"
|
||||
"\t-F - include directory names in onion names output\n"
|
||||
"\t-d dirname - output directory\n"
|
||||
"\t-t numthreads - specify number of threads (default - auto)\n"
|
||||
|
@ -479,6 +550,164 @@ static void setworkdir(const char *wd)
|
|||
|
||||
VEC_STRUCT(threadvec, pthread_t);
|
||||
|
||||
|
||||
int parseandcreate(const char *filepath, const char *hostname)
|
||||
{
|
||||
if (strlen(hostname) != ONION_LEN) {
|
||||
fprintf(stderr, "Invalid onion address \"%s\".\n", hostname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buf[16*1024];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
FILE *fkeys = fopen(filepath, "r");
|
||||
if (fkeys == NULL) {
|
||||
fprintf(stderr, "Cannot open file with keys \"%s\" for reading.\n", filepath);
|
||||
return 2;
|
||||
}
|
||||
int error_number = 1;
|
||||
size_t readbytes = 0;
|
||||
while (1) {
|
||||
const size_t currentread = fread(
|
||||
buf + readbytes, // Possibly we already partially receive desired onion address
|
||||
sizeof(buf[0]),
|
||||
sizeof(buf) - readbytes - NULLTERM_LEN,
|
||||
fkeys);
|
||||
if (currentread == 0) {
|
||||
fprintf(stderr, "Not found desired hostname \"%s\" in file \"%s\".\n", hostname, filepath);
|
||||
error_number = 3;
|
||||
break;
|
||||
}
|
||||
readbytes += currentread;
|
||||
buf[readbytes] = '\0';
|
||||
char *pfound = strstr(buf, hostname);
|
||||
if (pfound == NULL) {
|
||||
if (readbytes > ONION_LEN) {
|
||||
memmove(buf, buf + readbytes - ONION_LEN, ONION_LEN);
|
||||
readbytes = ONION_LEN;
|
||||
}
|
||||
} else { // Got it!
|
||||
memmove(buf, pfound, readbytes - (pfound - buf));
|
||||
readbytes -= pfound - buf;
|
||||
buf[readbytes] = '\0';
|
||||
char *pendrecord = NULL;
|
||||
while (1) {
|
||||
const size_t currentread = fread(
|
||||
buf + readbytes,
|
||||
sizeof(buf[0]),
|
||||
sizeof(buf) - readbytes - NULLTERM_LEN,
|
||||
fkeys);
|
||||
readbytes += currentread;
|
||||
buf[readbytes] = '\0';
|
||||
pendrecord = strstr(buf, "\n\n");
|
||||
if (pendrecord != NULL || currentread == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pendrecord == NULL) {
|
||||
fprintf(stderr, "Looks like file with keys \"%s\" is incomplete, found hostname but not keys.\n", filepath);
|
||||
error_number = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
const char *const pfield_sec_begin = strstr(buf, keys_field_secretkey);
|
||||
if (pfield_sec_begin == NULL) {
|
||||
fprintf(stderr, "Cannot find field with secret key within generated section.\n");
|
||||
error_number = 5;
|
||||
break;
|
||||
}
|
||||
const char *const p_sec_begin = pfield_sec_begin + KEYS_FIELD_SECRETKEY_LEN;
|
||||
if (pendrecord - p_sec_begin < BASE64_TO_LEN(FORMATTED_SECRET_LEN)) {
|
||||
fprintf(stderr, "Generated section it too small to keep base64 encoding of secret key.\n");
|
||||
error_number = 6;
|
||||
break;
|
||||
}
|
||||
char secbuf[FORMATTED_SECRET_LEN];
|
||||
if (-1 == base64_from((u8*)secbuf, p_sec_begin, BASE64_TO_LEN(FORMATTED_SECRET_LEN))) {
|
||||
fprintf(stderr, "Invalid base64 encoding of secret key.\n");
|
||||
error_number = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
const char *const pfield_pub_begin = strstr(buf, keys_field_publickey);
|
||||
if (pfield_pub_begin == NULL) {
|
||||
fprintf(stderr, "Cannot find field with public key within generated section.\n");
|
||||
error_number = 8;
|
||||
break;
|
||||
}
|
||||
const char *const p_pub_begin = pfield_pub_begin + KEYS_FIELD_PUBLICKEY_LEN;
|
||||
if (pendrecord - p_pub_begin < BASE64_TO_LEN(KEYS_FIELD_PUBLICKEY_LEN)) {
|
||||
fprintf(stderr, "Generated section it too small to keep base64 encoding of public key.\n");
|
||||
error_number = 9;
|
||||
break;
|
||||
}
|
||||
char pubbuf[FORMATTED_PUBLIC_LEN];
|
||||
if (-1 == base64_from((u8*)pubbuf, p_pub_begin, BASE64_TO_LEN(FORMATTED_PUBLIC_LEN))) {
|
||||
fprintf(stderr, "Invalid base64 encoding of secret key.\n");
|
||||
error_number = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
char pathbuf[1024];
|
||||
const size_t keys_directory_path_len = workdirlen + strlen(hostname);
|
||||
if (keys_directory_path_len >= sizeof(pathbuf)) {
|
||||
fprintf(stderr, "Keys directory path to is too long: %ld, max allowed length is %ld.\n", keys_directory_path_len, sizeof(pathbuf));
|
||||
error_number = 11;
|
||||
break;
|
||||
}
|
||||
strncpy(pathbuf, workdir, workdirlen);
|
||||
strncpy(pathbuf + workdirlen, hostname, strlen(hostname));
|
||||
pathbuf[keys_directory_path_len] = '\0';
|
||||
if (-1 == createdir(pathbuf, use_secret_mode)) {
|
||||
fprintf(stderr, "Cannot create directory \"%s\" for key files.\n", pathbuf);
|
||||
error_number = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t secretkey_filepath_len = keys_directory_path_len + PATH_SEPARATOR_LEN + strlen(secret_key_filename);
|
||||
if (secretkey_filepath_len >= sizeof(pathbuf)) {
|
||||
fprintf(stderr, "Path to file with secret key is too long %ld, max allowed length is %ld.\n", secretkey_filepath_len, sizeof(pathbuf));
|
||||
error_number = 13;
|
||||
break;
|
||||
}
|
||||
pathbuf[keys_directory_path_len] = '/';
|
||||
strncpy(pathbuf + keys_directory_path_len + PATH_SEPARATOR_LEN, secret_key_filename, strlen(secret_key_filename));
|
||||
pathbuf[secretkey_filepath_len] = '\0';
|
||||
if (-1 == writetofile(pathbuf, (u8*)secbuf, sizeof(secbuf), use_secret_mode)) {
|
||||
fprintf(stderr, "Can't write secret key to file \"%s\".\n", pathbuf);
|
||||
error_number = 14;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t publickey_filepath_len = keys_directory_path_len + PATH_SEPARATOR_LEN + strlen(public_key_filename);
|
||||
if (publickey_filepath_len >= sizeof(pathbuf)) {
|
||||
fprintf(stderr, "Path to file with public key is too long %ld, max allowed length is %ld.\n", publickey_filepath_len, sizeof(pathbuf));
|
||||
error_number = 15;
|
||||
break;
|
||||
}
|
||||
pathbuf[keys_directory_path_len] = '/';
|
||||
strncpy(pathbuf + keys_directory_path_len + PATH_SEPARATOR_LEN, public_key_filename, strlen(public_key_filename));
|
||||
pathbuf[publickey_filepath_len] = '\0';
|
||||
if (-1 == writetofile(pathbuf, (u8*)pubbuf, sizeof(pubbuf), use_public_mode)) {
|
||||
fprintf(stderr, "Can't write public key to file \"%s\".\n", pathbuf);
|
||||
error_number = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
pathbuf[keys_directory_path_len] = '\0';
|
||||
fprintf(stderr, "Keys successfully exported to directory \"%s\".\n", pathbuf);
|
||||
error_number = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(fkeys) || error_number) {
|
||||
fprintf(stderr, "Error #%d while parsing generated file \"%s\" or extracting keys.\n", error_number, filepath);
|
||||
}
|
||||
fclose(fkeys);
|
||||
return error_number;
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
const char *outfile = 0;
|
||||
|
@ -561,6 +790,27 @@ int main(int argc,char **argv)
|
|||
else
|
||||
e_additional();
|
||||
}
|
||||
else if (*arg == 'O') {
|
||||
if (argc--)
|
||||
outfilekeys = *argv++;
|
||||
else
|
||||
e_additional();
|
||||
}
|
||||
else if (*arg == 'i') {
|
||||
char * filepath = NULL;
|
||||
char * hostname = NULL;
|
||||
if (argc--) {
|
||||
filepath = *argv++;
|
||||
if (argc--) {
|
||||
hostname = *argv++;
|
||||
return parseandcreate(filepath, hostname);
|
||||
}
|
||||
else
|
||||
e_additional();
|
||||
}
|
||||
else
|
||||
e_additional();
|
||||
}
|
||||
else if (*arg == 'F')
|
||||
dirnameflag = 1;
|
||||
else if (*arg == 'd') {
|
||||
|
@ -626,7 +876,13 @@ int main(int argc,char **argv)
|
|||
filters_add(arg);
|
||||
}
|
||||
|
||||
if (outfile) {
|
||||
if (outfilekeys) {
|
||||
fout = fopen(outfilekeys,"a");
|
||||
if (!fout) {
|
||||
perror("failed to open output file for keys");
|
||||
exit(Q_FAILOPENOUTPUT);
|
||||
}
|
||||
} else if (outfile) {
|
||||
fout = fopen(outfile,"w");
|
||||
if (!fout) {
|
||||
perror("failed to open output file");
|
||||
|
@ -654,11 +910,11 @@ int main(int argc,char **argv)
|
|||
createdir(workdir,1);
|
||||
|
||||
direndpos = workdirlen;
|
||||
onionendpos = workdirlen + ONIONLEN;
|
||||
onionendpos = workdirlen + ONION_LEN;
|
||||
|
||||
if (!dirnameflag) {
|
||||
printstartpos = direndpos;
|
||||
printlen = ONIONLEN + 1;
|
||||
printlen = ONION_LEN + 1;
|
||||
} else {
|
||||
printstartpos = 0;
|
||||
printlen = onionendpos + 1;
|
||||
|
|
44
test_base64.c
Normal file
44
test_base64.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "types.h"
|
||||
#include "base64.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sodium/randombytes.h>
|
||||
|
||||
struct texttestcase {
|
||||
const char *in;
|
||||
const char *out;
|
||||
const char *rev;
|
||||
} tests0[] = {
|
||||
{"", "", ""},
|
||||
{"f", "Zg==", "f"},
|
||||
{"fo", "Zm8=", "fo"},
|
||||
{"foo", "Zm9v", "foo"},
|
||||
{"foob", "Zm9vYg==", "foob"},
|
||||
{"fooba", "Zm9vYmE=", "fooba"},
|
||||
{"foobar", "Zm9vYmFy", "foobar"},
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char buf[1024], buf2[1024];
|
||||
size_t r;
|
||||
for (size_t i = 0; i < sizeof(tests0)/sizeof(tests0[0]); ++i) {
|
||||
base64_to(buf, (const u8 *)tests0[i].in, strlen(tests0[i].in));
|
||||
if (strcmp(buf, tests0[i].out) != 0) {
|
||||
printf("invalid encoding result: \"%s\" -> encoded as \"%s\", but expected \"%s\".\n",
|
||||
tests0[i].in, buf, tests0[i].out);
|
||||
return 1;
|
||||
}
|
||||
r = base64_from((u8 *)buf2, buf, strlen(buf));
|
||||
buf2[r] = '\0';
|
||||
if (strcmp(buf2, tests0[i].rev) != 0) {
|
||||
printf("invalid decoding result: encoded \"%s\", decoded as \"%s\", but expected \"%s\".\n",
|
||||
tests0[i].out, buf2, tests0[i].rev);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue