| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 | #include <stdio.h>#include <string.h>#include <openssl/rand.h>#include <openssl/sha.h>#include "ptwist.h"byte maingen[PTWIST_BYTES];byte twistgen[PTWIST_BYTES];byte mainpub[PTWIST_BYTES];byte twistpub[PTWIST_BYTES];static void gen_tag(byte tag[PTWIST_TAG_BYTES], byte key[16],	const byte *context, size_t context_len){    byte seckey[PTWIST_BYTES];    byte sharedsec[PTWIST_BYTES+context_len];    byte usetwist;    byte taghashout[32];#if PTWIST_PUZZLE_STRENGTH > 0    size_t puzzle_len = 16+PTWIST_RESP_BYTES;    byte value_to_hash[puzzle_len];    byte hashout[32];    bn_t Rbn, Hbn;    int i, len, sign;#endif    memset(tag, 0xAA, PTWIST_TAG_BYTES);    /* Use the main or the twist curve? */    RAND_bytes(&usetwist, 1);    usetwist &= 1;    /* Create seckey*G and seckey*Y */    RAND_bytes(seckey, PTWIST_BYTES);    ptwist_pointmul(tag, usetwist ? twistgen : maingen, seckey);    ptwist_pointmul(sharedsec, usetwist ? twistpub : mainpub, seckey);    /* Create the tag hash keys */    memmove(sharedsec+PTWIST_BYTES, context, context_len);    SHA256(sharedsec, PTWIST_BYTES, taghashout);#if PTWIST_PUZZLE_STRENGTH > 0    /* The puzzle is to find a response R such that SHA256(K || R)       starts with PTWIST_PUZZLE_STRENGTH bits of 0s.  K is the first       128 bits of the above hash tag keys. */    /* Construct our response to the puzzle.  Start looking for R in a     * random place. */    memmove(value_to_hash, taghashout, 16);    RAND_bytes(value_to_hash+16, PTWIST_RESP_BYTES);    value_to_hash[16+PTWIST_RESP_BYTES-1] &= PTWIST_RESP_MASK;    while(1) {	unsigned int firstbits;	md_map_sh256(hashout, value_to_hash, puzzle_len);#if PTWIST_PUZZLE_STRENGTH < 32	/* This assumes that you're on an architecture that doesn't care	 * about alignment, and is little endian. */	firstbits = *(unsigned int*)hashout;	if ((firstbits & PTWIST_PUZZLE_MASK) == 0) {	    break;	}	/* Increment R and try again. */	for(i=0;i<PTWIST_RESP_BYTES;++i) {	    if (++value_to_hash[16+i]) break;	}	value_to_hash[16+PTWIST_RESP_BYTES-1] &= PTWIST_RESP_MASK;#else#error "Code assumes PTWIST_PUZZLE_STRENGTH < 32"#endif    }	/*	for(i=0;i<puzzle_len;++i) {	    printf("%02x", value_to_hash[i]);	    if ((i%4) == 3) printf(" ");	}	printf("\n");	for(i=0;i<32;++i) {	    printf("%02x", hashout[i]);	    if ((i%4) == 3) printf(" ");	}	printf("\n");	*/    /* When we get here, we have solved the puzzle.  R is in     * value_to_hash[16..16+PTWIST_RESP_BYTES-1], the hash output     * hashout starts with PTWIST_PUZZLE_STRENGTH bits of 0s, and we'll     * want to copy out H (the next PTWIST_HASH_SHOWBITS bits of the     * hash output).  The final tag is [seckey*G]_x || R || H . */    bn_new(Rbn);    bn_new(Hbn);    bn_read_bin(Rbn, value_to_hash+16, PTWIST_RESP_BYTES, BN_POS);    hashout[PTWIST_HASH_TOTBYTES-1] &= PTWIST_HASH_MASK;    bn_read_bin(Hbn, hashout, PTWIST_HASH_TOTBYTES, BN_POS);    bn_lsh(Hbn, Hbn, PTWIST_RESP_BITS-PTWIST_PUZZLE_STRENGTH);    bn_add(Hbn, Hbn, Rbn);    len = PTWIST_TAG_BYTES-PTWIST_BYTES;    bn_write_bin(tag+PTWIST_BYTES, &len, &sign, Hbn);	/*	for(i=0;i<PTWIST_TAG_BYTES;++i) {	    printf("%02x", tag[i]);	    if ((i%4) == 3) printf(" ");	}	printf("\n");	*/    bn_free(Rbn);    bn_free(Hbn);#elif PTWIST_HASH_SHOWBITS <= 128    /* We're not using a client puzzle, so the tag is [seckey*G]_x || H     * where H is the first PTWIST_HASH_SHOWBITS bits of the above hash     * output.  The key generated is the last 128 bits of that output.     * If there's no client puzzle, PTWIST_HASH_SHOWBITS must be a multiple     * of 8. */    memmove(tag+PTWIST_BYTES, taghashout, PTWIST_HASH_SHOWBITS/8);#else#error "No client puzzle used, but PWTIST_HASH_SHOWBITS > 128"#endif    memmove(key, taghashout+16, 16);}int main(int argc, char **argv){    FILE *fp;    int res;    int i;    byte tag[PTWIST_TAG_BYTES];    int numtags = argc > 1 ? atoi(argv[1]) : 10;    /* Create the generators */    memset(maingen, 0, PTWIST_BYTES);    maingen[0] = 2;    memset(twistgen, 0, PTWIST_BYTES);    /* Read the public keys */    fp = fopen("pubkey", "rb");    if (fp == NULL) {	perror("fopen");	exit(1);    }    res = fread(mainpub, PTWIST_BYTES, 1, fp);    if (res < 1) {	perror("fread");	exit(1);    }    res = fread(twistpub, PTWIST_BYTES, 1, fp);    if (res < 1) {	perror("fread");	exit(1);    }    fclose(fp);    fp = fopen("tags", "wb");    if (fp == NULL) {	perror("fopen");	exit(1);    }    for(i=0;i<numtags;++i) {	byte key[16];#if 0	int j;#endif	gen_tag(tag, key, (const byte *)"context", 7);	fwrite(tag, PTWIST_TAG_BYTES, 1, fp);#if 0	for(j=0;j<16;++j) {	    printf("%02x", key[j]);	}	printf("\n");#endif    }    fclose(fp);    return 0;}
 |