예제 #1
0
파일: sign.c 프로젝트: AEtherC0r3/Vault
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
    sha512_context hash;
    unsigned char hram[64];
    unsigned char r[64];
    ge_p3 R;


    sha512_init(&hash);
    sha512_update(&hash, private_key + 32, 32);
    sha512_update(&hash, message, message_len);
    sha512_final(&hash, r);

    sc_reduce(r);
    ge_scalarmult_base(&R, r);
    ge_p3_tobytes(signature, &R);

    sha512_init(&hash);
    sha512_update(&hash, signature, 32);
    sha512_update(&hash, public_key, 32);
    sha512_update(&hash, message, message_len);
    sha512_final(&hash, hram);

    sc_reduce(hram);
    sc_muladd(signature + 32, hram, private_key, r);
}
예제 #2
0
void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac,
                       unsigned int mac_size)
{
    unsigned char digest_inside[SHA512_DIGEST_SIZE];
    unsigned char mac_temp[SHA512_DIGEST_SIZE];

    sha512_final(&ctx->ctx_inside, digest_inside);
    sha512_update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_SIZE);
    sha512_final(&ctx->ctx_outside, mac_temp);
    memcpy(mac, mac_temp, mac_size);
}
예제 #3
0
파일: prf.c 프로젝트: meshlink/meshlink
static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) {
	char tmp[2 * mdlen];
	sha512_context md;

	if(keylen <= mdlen) {
		memcpy(tmp, key, keylen);
		memset(tmp + keylen, 0, mdlen - keylen);
	} else {
		if(sha512(key, keylen, tmp) != 0)
			return false;
	}

	if(sha512_init(&md) != 0)
		return false;

	// ipad
	memxor(tmp, 0x36, mdlen);
	if(sha512_update(&md, tmp, mdlen) != 0)
		return false;

	// message
	if(sha512_update(&md, msg, msglen) != 0)
		return false;

	if(sha512_final(&md, tmp + mdlen) != 0)
		return false;

	// opad
	memxor(tmp, 0x36 ^ 0x5c, mdlen);
	if(sha512(tmp, sizeof tmp, out) != 0)
		return false;

	return true;
}
예제 #4
0
int
goldilocks_derive_private_key (
    struct goldilocks_private_key_t *privkey,
    const unsigned char proto[GOLDI_SYMKEY_BYTES]
) {
    if (!goldilocks_check_init()) {
        return GOLDI_EUNINIT;
    }

    memcpy(&privkey->opaque[2*GOLDI_FIELD_BYTES], proto, GOLDI_SYMKEY_BYTES);

    unsigned char skb[SHA512_OUTPUT_BYTES];
    word_t sk[GOLDI_FIELD_WORDS];
    assert(sizeof(skb) >= sizeof(sk));

    struct sha512_ctx_t ctx;
    struct tw_extensible_t exta;
    struct field_t pk;

    sha512_init(&ctx);
    sha512_update(&ctx, (const unsigned char *)"derivepk", GOLDI_DIVERSIFY_BYTES);
    sha512_update(&ctx, proto, GOLDI_SYMKEY_BYTES);
    sha512_final(&ctx, (unsigned char *)skb);

    barrett_deserialize_and_reduce(sk, skb, SHA512_OUTPUT_BYTES, &curve_prime_order);
    barrett_serialize(privkey->opaque, sk, GOLDI_FIELD_BYTES);

    scalarmul_fixed_base(&exta, sk, GOLDI_SCALAR_BITS, &goldilocks_global.fixed_base);
    untwist_and_double_and_serialize(&pk, &exta);

    field_serialize(&privkey->opaque[GOLDI_FIELD_BYTES], &pk);

    return GOLDI_EOK;
}
예제 #5
0
파일: SHA512.cpp 프로젝트: WeijieH/HashME
unsigned char* sha512_MemBlock(const unsigned char* msg, size_t size, HASH_ctx* ctx)
{
    sha512_init(ctx);
    sha512_update(ctx, msg, size);
    sha512_final(ctx, msg, size);
    return ctx->SHA512_result;
}
예제 #6
0
파일: libcrypto.c 프로젝트: cedral/libssh
void sha512(unsigned char *digest, int len, unsigned char *hash)
{
    SHA512CTX c = sha512_init();
    if (c != NULL) {
        sha512_update(c, digest, len);
        sha512_final(hash, c);
    }
}
예제 #7
0
void sha512(const unsigned char *message, unsigned int len,
            unsigned char *digest)
{
    sha512_ctx ctx;

    sha512_init(&ctx);
    sha512_update(&ctx, message, len);
    sha512_final(&ctx, digest);
}
예제 #8
0
		void SHA512Hash::Finalize()
		{
			CoreAssert(this != NULL);

			if (m_hash) delete [] m_hash;

			m_hash = new unsigned char[SHA512_DIGEST_SIZE];
			sha512_final(&m_state, m_hash);
		}
예제 #9
0
static void sha384_final(struct crypto_tfm *tfm, u8 *out)
{
	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
	u8 hash[SHA512_DIGEST_SIZE];

	sha512_final(tfm, hash);

	memcpy(out, hash, SHA384_DIGEST_SIZE);		/* copy digest to out */
	memset(sctx, 0, sizeof *sctx);			/* wipe context */
}
std::string BackupServerPrepareHash::hash_with_patch(IFile *f, IFile *patch)
{
	sha512_init(&ctx);
	
	chunk_patcher.ApplyPatch(f, patch);

	std::string ret;
	ret.resize(64);
	sha512_final(&ctx, (unsigned char*)&ret[0]);
	return ret;
}
예제 #11
0
int sha512(const unsigned char *message, size_t message_len, unsigned char *out)
{
    sha512_context ctx;
    int ret;
    ret = sha512_init(&ctx);
    if (ret) return ret;
    ret = sha512_update(&ctx, message, message_len);
    if (ret) return ret;
    ret = sha512_final(&ctx, out);
    if (ret) return ret;
    return 0;
}
예제 #12
0
		int SHA512Hash::Process(const void * _data, size_t _length)
		{
			CoreAssert(this != NULL);

			Reset();
			if (!_length || !_data) return -1;

			sha512_update(&m_state, (const unsigned char *)_data, (unsigned int)_length);
			m_hash = new unsigned char[SHA512_DIGEST_SIZE];
			sha512_final(&m_state, m_hash);
			return 0;
		}
예제 #13
0
파일: sha512.c 프로젝트: meshlink/meshlink
int sha512(const void *message, size_t message_len, void *out)
{
	sha512_context ctx;
	int ret;
	if ((ret = sha512_init(&ctx)))
		return ret;
	if ((ret = sha512_update(&ctx, message, message_len)))
		return ret;
	if ((ret = sha512_final(&ctx, out)))
		return ret;
	return 0;
}
예제 #14
0
void inline sha512_result(sha512_context *ctx, u_int8_t * hash, int hashlen) {
#ifdef HAVE_LIBNSS
	unsigned int len;
	SECStatus s;
	s=PK11_DigestFinal(ctx->DigestContext, hash, &len, hashlen);
	PR_ASSERT(len==hashlen);
	PR_ASSERT(s==SECSuccess);
	PK11_DestroyContext(ctx->DigestContext, PR_TRUE);
#else
	sha512_final(ctx);
	memcpy(hash, &ctx->sha_out[0], hashlen);
#endif
}
예제 #15
0
ssh_string SshAgentSignEcdsaSha512(uint8_t* data, int dataSize, ssh_key key, uint32_t flags)
{
    // Compute the hash.
    unsigned char hash[SHA384_DIGEST_LEN] = {0};
    SHACTX ctx;
    
    ctx = sha512_init();
    if (ctx == NULL)
    {
        return NULL;
    }
    
    sha512_update(ctx, data, dataSize);
    sha512_final(hash, ctx);   // This release ctx.
    
    // Sign the hash.
    ECDSA_SIG* sig = NULL;
    sig = ECDSA_do_sign(hash, sizeof(hash), key->ecdsa);
    if (sig == NULL)
    {
        return NULL;
    }
    
    // Format the signature in a blob of the form:
    // blobLength[ typeNameLength[ typeName ] signatureLength[ rLength[ r ] sLength[ s ] ] ]
    int rMpiLength = BN_bn2mpi(sig->r, NULL);
    int sMpiLength = BN_bn2mpi(sig->s, NULL);
    int signatureLength = rMpiLength + sMpiLength;
    int typeNameLength = 19;
    int blobLength = 8 + typeNameLength + signatureLength;
    
    uint8_t* signatureBlob = malloc(4 + blobLength);
    if (signatureBlob == NULL)
    {
        return NULL;
    }
    
    pack32(signatureBlob, blobLength);
    int index = 4;
    pack32(signatureBlob + index, typeNameLength);
    index += 4;
    memcpy(signatureBlob + index, "ecdsa-sha2-nistp521", typeNameLength);
    index += typeNameLength;
    pack32(signatureBlob + 15, signatureLength);
    index += 4;
    BN_bn2mpi(sig->r, signatureBlob + index);
    index += rMpiLength;
    BN_bn2mpi(sig->s, signatureBlob + index);
    
    return (ssh_string)signatureBlob;
}
예제 #16
0
static int sha512_monte_carlo_core (
    const char *seed,
    const char *checks[100]
) { 
    struct sha512_ctx_t sha;
    sha512_init(&sha);
    
    unsigned char md0[64],md1[64],md2[64];
    
    int ret = hexdecode(md0,seed,64);
    if (ret) {
        youfail();
        printf("    SHA-512 NIST Monte Carlo validation seed hex decode failure.\n");
        return -1;
    }
    
    int i,j;

    memcpy(md1,md0,sizeof(md1));
    memcpy(md2,md0,sizeof(md1));
    
    for (j=0; j<100; j++) {
        
        for (i=3; i<1003; i++) {
            sha512_update(&sha,md0,sizeof(md0));
            sha512_update(&sha,md1,sizeof(md1));
            sha512_update(&sha,md2,sizeof(md2));
            memcpy(md0,md1,sizeof(md1));
            memcpy(md1,md2,sizeof(md1));
            sha512_final(&sha,md2);
        }
        
        ret = hexdecode(md0,checks[j],64);
        if (ret) {
            youfail();
            printf("    SHA-512 NIST Monte Carlo validation hex decode failure at iteration %d\n", j);
            return -1;
        } else if (memcmp(md0,md2,sizeof(md2))) {
            youfail();
            printf("    SHA-512 NIST Monte Carlo validation failure at iteration %d\n", j);
            hexprint("    Expected", md0, 64);
            hexprint("    But got ", md2, 64);
            return j+1;
        }
        
        memcpy(md0,md2,sizeof(md1));
        memcpy(md1,md2,sizeof(md1));
    }
    
    return 0;
}
예제 #17
0
static void sha512_hash_final(u_char *hash, sha512_context *ctx)
{
#ifdef HAVE_LIBNSS
	unsigned int len;
	SECStatus s;
	s = PK11_DigestFinal(ctx->ctx_nss, hash, &len, SHA2_512_DIGEST_SIZE);
	PR_ASSERT(len==SHA2_512_DIGEST_SIZE);
	PR_ASSERT(s==SECSuccess);
	PK11_DestroyContext(ctx->ctx_nss, PR_TRUE);
	DBG(DBG_CRYPT, DBG_log("NSS SHA 512 hash final : end"));
#else
	sha512_final(ctx);
	memcpy(hash, &ctx->sha_out[0], SHA2_512_DIGEST_SIZE);
#endif
}
예제 #18
0
ssh_string SshAgentSignRsaSha512(uint8_t* data, int dataSize, ssh_key key, uint32_t flags)
{
    // Compute the hash.
    unsigned char hash[SHA512_DIGEST_LEN] = {0};
    SHACTX ctx;
    
    ctx = sha512_init();
    if (ctx == NULL)
    {
        return NULL;
    }
    
    sha512_update(ctx, data, dataSize);
    sha512_final(hash, ctx);   // This release ctx.
    
    // Prepare the buffer to hold the signature in a blob of the form:
    // signatureBlobLength[ signatureTypeLength[ signatureType ] signatureLength[ signature ] ]
    int signatureTypeLength = 12;
    int signatureLength = RSA_size(key->rsa);
    int signatureBlobLength = 8 + signatureTypeLength + signatureLength;
    
    uint8_t* signatureBlob = malloc(4 + signatureBlobLength);
    if (signatureBlob == NULL)
    {
        return NULL;
    }
    
    pack32(signatureBlob, signatureBlobLength);
    int index = 4;
    pack32(signatureBlob + index, signatureTypeLength);
    index += 4;
    memcpy(signatureBlob + index, "rsa-sha2-512", signatureTypeLength);
    index += signatureTypeLength;
    pack32(signatureBlob + 15, signatureLength);
    index += 4;
    
    // Sign the hash in place in the signature blob buffer.
    unsigned int len;
    int result = RSA_sign(NID_sha512, hash, sizeof(hash), signatureBlob + index, &len, key->rsa);
    if (result != 1)
    {
        free(signatureBlob);
        return NULL;
    }
    
    return (ssh_string)signatureBlob;
}
예제 #19
0
파일: pairing.c 프로젝트: juhovh/shairplay
static int
derive_key_internal(pairing_session_t *session, const unsigned char *salt, unsigned int saltlen, unsigned char *key, unsigned int keylen)
{
	sha512_context ctx;
	unsigned char hash[64];

	if (keylen > sizeof(hash)) {
		return -1;
	}
	sha512_init(&ctx);
	sha512_update(&ctx, salt, saltlen);
	sha512_update(&ctx, session->ecdh_secret, 32);
	sha512_final(&ctx, hash);

	memcpy(key, hash, keylen);
	return 0;
}
예제 #20
0
static void
goldilocks_derive_challenge(
    word_t challenge[GOLDI_FIELD_WORDS],
    const unsigned char pubkey[GOLDI_FIELD_BYTES],
    const unsigned char gnonce[GOLDI_FIELD_BYTES],
    const unsigned char *message,
    uint64_t message_len
) {
    /* challenge = H(pk, [nonceG], message). */
    unsigned char sha_out[SHA512_OUTPUT_BYTES];
    struct sha512_ctx_t ctx;
    sha512_init(&ctx);
    sha512_update(&ctx, pubkey, GOLDI_FIELD_BYTES);
    sha512_update(&ctx, gnonce, GOLDI_FIELD_BYTES);
    sha512_update(&ctx, message, message_len);
    sha512_final(&ctx, sha_out);
    barrett_deserialize_and_reduce(challenge, sha_out, sizeof(sha_out), &curve_prime_order);
}
예제 #21
0
파일: libcrypto.c 프로젝트: codinn/libssh
void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
  switch(ctx->mac_type){
    case SSH_MAC_SHA1:
      sha1_final(md,ctx->ctx.sha1_ctx);
      break;
    case SSH_MAC_SHA256:
      sha256_final(md,ctx->ctx.sha256_ctx);
      break;
    case SSH_MAC_SHA384:
      sha384_final(md,ctx->ctx.sha384_ctx);
      break;
    case SSH_MAC_SHA512:
      sha512_final(md,ctx->ctx.sha512_ctx);
      break;
    default:
      break;
  }
  SAFE_FREE(ctx);
}
std::string BackupServerPrepareHash::hash(IFile *f)
{
	f->Seek(0);
	unsigned char buf[4096];
	_u32 rc;

	sha512_init(&ctx);
	do
	{
		rc=f->Read((char*)buf, 4096);
		if(rc>0)
			sha512_update(&ctx, buf, rc);
	}
	while(rc==4096);
	
	std::string ret;
	ret.resize(64);
	sha512_final(&ctx, (unsigned char*)&ret[0]);
	return ret;
}
예제 #23
0
파일: key.c 프로젝트: kevinconway/HashRot
void hash_from_keyfile(char* keyfile_name, unsigned char* hash) {

    FILE* key = fopen(keyfile_name, "rb");
    unsigned char buffer[64];
    register short bytes = 0;
    sha512_ctx ctx;

    sha512_init(&ctx);

    bytes = fread(buffer, 1, 64, key);

    while (bytes > 0) {

        sha512_update(&ctx, buffer, bytes);

        bytes = fread(buffer, 1, 64, key);

    }

    sha512_final(&ctx, hash);

    fclose(key);

}
예제 #24
0
파일: sha2.c 프로젝트: Kotty666/xymon
void mySHA512_Final(char md[20], void *c) { sha512_final((sha512_ctx *)c, md); }
예제 #25
0
/* see http://crypto.stackexchange.com/a/6215/4697 */
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
    const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
    
    unsigned char n[32]; 
    ge_p3 nB;
    ge_p1p1 A_p1p1;
    ge_p3 A;
    ge_p3 public_key_unpacked;
    ge_cached T;

    sha512_context hash;
    unsigned char hashbuf[64];

    int i;

    /* copy the scalar and clear highest bit */
    for (i = 0; i < 31; ++i) {
        n[i] = scalar[i];
    }
    n[31] = scalar[31] & 127;

    /* private key: a = n + t */
    if (private_key) {
        sc_muladd(private_key, SC_1, n, private_key);

        // https://github.com/orlp/ed25519/issues/3
        sha512_init(&hash);
        sha512_update(&hash, private_key + 32, 32);
        sha512_update(&hash, scalar, 32);
        sha512_final(&hash, hashbuf);
        for (i = 0; i < 32; ++i) {
            private_key[32 + i] = hashbuf[i];
        }
    }

    /* public key: A = nB + T */
    if (public_key) {
        /* if we know the private key we don't need a point addition, which is faster */
        /* using a "timing attack" you could find out wether or not we know the private
           key, but this information seems rather useless - if this is important pass
           public_key and private_key seperately in 2 function calls */
        if (private_key) {
            ge_scalarmult_base(&A, private_key);
        } else {
            /* unpack public key into T */
            ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
            fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */
            fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */
            ge_p3_to_cached(&T, &public_key_unpacked);

            /* calculate n*B */
            ge_scalarmult_base(&nB, n);

            /* A = n*B + T */
            ge_add(&A_p1p1, &nB, &T);
            ge_p1p1_to_p3(&A, &A_p1p1);
        }
            
        /* pack public key */
        ge_p3_tobytes(public_key, &A);
    }
}
예제 #26
0
bool protoshares_revalidateCollision(minerProtosharesBlock_t* block, uint8* midHash, uint32 indexA, uint32 indexB)
{
    uint8 tempHash[32 + 4];
    uint64 resultHash[8];
    memcpy(tempHash + 4, midHash, 32);
    // get birthday A
    *(uint32*)tempHash = indexA & ~7; // indexA & ~7 == indexA - (indexA % BIRTHDAYS_PER_HASH)
    sha512_ctx c512;
    sha512_init(&c512);
    sha512_update(&c512, tempHash, 32 + 4);
    sha512_final(&c512, (unsigned char*)resultHash);
    uint64 birthdayA = resultHash[indexA & 7] >> (64ULL - SEARCH_SPACE_BITS);

    // get birthday B
    *(uint32*)tempHash = indexB & ~7;
    sha512_init(&c512);
    sha512_update(&c512, tempHash, 32 + 4);
    sha512_final(&c512, (unsigned char*)resultHash);
    uint64 birthdayB = resultHash[indexB & 7] >> (64ULL - SEARCH_SPACE_BITS);

#ifdef VERIFY_RESULTS
    printf("Nonce Pair:\n");
    printf("    Nonce A = %#010x; Hash A = %#018llx\n", indexA, birthdayA);
    printf("    Nonce B = %#010x; Hash B = %#018llx\n", indexB, birthdayB);
    printf("\n");
#endif

    if ( birthdayA != birthdayB ) {
        return false; // invalid collision
    }

    // birthday collision found
    totalCollisionCount += 2; // we can use every collision twice -> A B and B A
    //printf("Collision found %8d = %8d | num: %d\n", indexA, indexB, totalCollisionCount);
    // get full block hash (for A B)
    block->birthdayA = indexA;
    block->birthdayB = indexB;
    uint8 proofOfWorkHash[32];
    sha256_ctx c256;
    sha256_init(&c256);
    sha256_update(&c256, (unsigned char*)block, 80 + 8);
    sha256_final(&c256, proofOfWorkHash);
    sha256_init(&c256);
    sha256_update(&c256, (unsigned char*)proofOfWorkHash, 32);
    sha256_final(&c256, proofOfWorkHash);
    bool hashMeetsTarget = true;
    uint32* generatedHash32 = (uint32*)proofOfWorkHash;
    uint32* targetHash32 = (uint32*)block->targetShare;

    for (sint32 hc = 7; hc >= 0; hc--) {
        if ( generatedHash32[hc] < targetHash32[hc] ) {
            hashMeetsTarget = true;
            break;
        } else if ( generatedHash32[hc] > targetHash32[hc] ) {
            hashMeetsTarget = false;
            break;
        }
    }

    if ( hashMeetsTarget ) {
        totalShareCount++;
        curShareCount++;
#ifndef NOSUBMIT
        xptMiner_submitShare(block);
#endif
    }

    // get full block hash (for B A)
    block->birthdayA = indexB;
    block->birthdayB = indexA;
    sha256_init(&c256);
    sha256_update(&c256, (unsigned char*)block, 80 + 8);
    sha256_final(&c256, proofOfWorkHash);
    sha256_init(&c256);
    sha256_update(&c256, (unsigned char*)proofOfWorkHash, 32);
    sha256_final(&c256, proofOfWorkHash);
    hashMeetsTarget = true;
    generatedHash32 = (uint32*)proofOfWorkHash;
    targetHash32 = (uint32*)block->targetShare;

    for (sint32 hc = 7; hc >= 0; hc--) {
        if ( generatedHash32[hc] < targetHash32[hc] ) {
            hashMeetsTarget = true;
            break;
        } else if ( generatedHash32[hc] > targetHash32[hc] ) {
            hashMeetsTarget = false;
            break;
        }
    }

    if ( hashMeetsTarget ) {
        totalShareCount++;
        curShareCount++;
#ifndef NOSUBMIT
        xptMiner_submitShare(block);
#endif
    }

    return true;
}
예제 #27
0
int crypto_sha512_finup(struct shash_desc *desc, const u8 *data,
			unsigned int len, u8 *hash)
{
	sha512_base_do_update(desc, data, len, sha512_generic_block_fn);
	return sha512_final(desc, hash);
}
예제 #28
0
static void sha512_final_thunk(u_char *hash, union hash_ctx *ctx)
{
	sha512_final(hash, &ctx->ctx_sha512);
}
예제 #29
0
int main(int argc, char **argv) {
    (void)argc;
    (void)argv;

    struct tw_extensible_t ext;
    struct extensible_t exta;
    struct tw_niels_t niels;
    struct tw_pniels_t pniels;
    struct affine_t affine;
    struct montgomery_t mb;
    field_a_t a,b,c,d;
    
    
    double when;
    int i;

    int nbase = N_TESTS_BASE;
    
    /* Bad randomness so we can debug. */
    char initial_seed[32];
    for (i=0; i<32; i++) initial_seed[i] = i;
    struct crandom_state_t crand;
    crandom_init_from_buffer(&crand, initial_seed);
    /* For testing the performance drop from the crandom debuffering change.
        ignore_result(crandom_init_from_file(&crand, "/dev/urandom", 10000, 1));
    */
    
    word_t sk[SCALAR_WORDS],tk[SCALAR_WORDS];
    q448_randomize(&crand, sk);
    
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    memset(d,0,sizeof(d));
    when = now();
    for (i=0; i<nbase*5000; i++) {
        field_mul(c, b, a);
    }
    when = now() - when;
    printf("mul:         %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*5000; i++) {
        field_sqr(c, a);
    }
    when = now() - when;
    printf("sqr:         %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*5000; i++) {
        field_mulw(c, b, 1234562);
    }
    when = now() - when;
    printf("mulw:        %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*500; i++) {
        field_mul(c, b, a);
        field_mul(a, b, c);
    }
    when = now() - when;
    printf("mul dep:     %5.1fns\n", when * 1e9 / i / 2);
    
    when = now();
    for (i=0; i<nbase*10; i++) {
        field_randomize(&crand, a);
    }
    when = now() - when;
    printf("rand448:     %5.1fns\n", when * 1e9 / i);
    
    sha512_ctx_a_t sha;
    uint8_t hashout[128];
    when = now();
    for (i=0; i<nbase; i++) {
        sha512_init(sha);
        sha512_final(sha, hashout);
    }
    when = now() - when;
    printf("sha512 1blk: %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase; i++) {
        sha512_update(sha, hashout, 128);
    }
    when = now() - when;
    printf("sha512 blk:  %5.1fns (%0.2f MB/s)\n", when * 1e9 / i, 128*i/when/1e6);
    
    when = now();
    for (i=0; i<nbase; i++) {
        field_isr(c, a);
    }
    when = now() - when;
    printf("isr auto:    %5.1fµs\n", when * 1e6 / i);
    
    for (i=0; i<100; i++) {
        field_randomize(&crand, a);
        field_isr(d,a);
        field_sqr(b,d);
        field_mul(c,b,a);
        field_sqr(b,c);
        field_subw(b,1);
        if (!field_is_zero(b)) {
            printf("ISR validation failure!\n");
            field_print("a", a);
            field_print("s", d);
        }
    }
    
    when = now();
    for (i=0; i<nbase; i++) {
        elligator_2s_inject(&affine, a);
    }
    when = now() - when;
    printf("elligator:   %5.1fµs\n", when * 1e6 / i);
    
    for (i=0; i<100; i++) {
        field_randomize(&crand, a);
        elligator_2s_inject(&affine, a);
        if (!validate_affine(&affine)) {
            printf("Elligator validation failure!\n");
            field_print("a", a);
            field_print("x", affine.x);
            field_print("y", affine.y);
        }
    }
    
    when = now();
    for (i=0; i<nbase; i++) {
        deserialize_affine(&affine, a);
    }
    when = now() - when;
    printf("decompress:  %5.1fµs\n", when * 1e6 / i);
    
    convert_affine_to_extensible(&exta, &affine);
    when = now();
    for (i=0; i<nbase; i++) {
        serialize_extensible(a, &exta);
    }
    when = now() - when;
    printf("compress:    %5.1fµs\n", when * 1e6 / i);
    
    int goods = 0;
    for (i=0; i<100; i++) {
        field_randomize(&crand, a);
        mask_t good = deserialize_affine(&affine, a);
        if (good & !validate_affine(&affine)) {
            printf("Deserialize validation failure!\n");
            field_print("a", a);
            field_print("x", affine.x);
            field_print("y", affine.y);
        } else if (good) {
            goods++;
            convert_affine_to_extensible(&exta,&affine);
            serialize_extensible(b, &exta);
            field_sub(c,b,a);
            if (!field_is_zero(c)) {
                printf("Reserialize validation failure!\n");
                field_print("a", a);
                field_print("x", affine.x);
                field_print("y", affine.y);
                deserialize_affine(&affine, b);
                field_print("b", b);
                field_print("x", affine.x);
                field_print("y", affine.y);
                printf("\n");
            }
        }
    }
    if (goods<i/3) {
        printf("Deserialization validation failure! Deserialized %d/%d points\n", goods, i);
    }
    
    word_t lsk[768/WORD_BITS];
    crandom_generate(&crand, (unsigned char *)lsk, sizeof(lsk));
    
    when = now();
    for (i=0; i<nbase*100; i++) {
        barrett_reduce(lsk,sizeof(lsk)/sizeof(word_t),0,&curve_prime_order);
    }
    when = now() - when;
    printf("barrett red: %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*10; i++) {
        barrett_mac(lsk,SCALAR_WORDS,lsk,SCALAR_WORDS,lsk,SCALAR_WORDS,&curve_prime_order);
    }
    when = now() - when;
    printf("barrett mac: %5.1fns\n", when * 1e9 / i);
    
    memset(&ext,0,sizeof(ext));
    memset(&niels,0,sizeof(niels)); /* avoid assertions in p521 even though this isn't a valid ext or niels */
    when = now();
    for (i=0; i<nbase*100; i++) {
        add_tw_niels_to_tw_extensible(&ext, &niels);
    }
    when = now() - when;
    printf("exti+niels:  %5.1fns\n", when * 1e9 / i);
    
    convert_tw_extensible_to_tw_pniels(&pniels, &ext);
    when = now();
    for (i=0; i<nbase*100; i++) {
        add_tw_pniels_to_tw_extensible(&ext, &pniels);
    }
    when = now() - when;
    printf("exti+pniels: %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*100; i++) {
        double_tw_extensible(&ext);
    }
    when = now() - when;
    printf("exti dbl:    %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*100; i++) {
        untwist_and_double(&exta, &ext);
    }
    when = now() - when;
    printf("i->a isog:   %5.1fns\n", when * 1e9 / i);
    
    when = now();
    for (i=0; i<nbase*100; i++) {
        twist_and_double(&ext, &exta);
    }
    when = now() - when;
    printf("a->i isog:   %5.1fns\n", when * 1e9 / i);
    
    memset(&mb,0,sizeof(mb));
    when = now();
    for (i=0; i<nbase*100; i++) {
        montgomery_step(&mb);
    }
    when = now() - when;
    printf("monty step:  %5.1fns\n", when * 1e9 / i);
	
    when = now();
    for (i=0; i<nbase/10; i++) {
        ignore_result(montgomery_ladder(a,b,sk,FIELD_BITS,0));
    }
    when = now() - when;
    printf("full ladder: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        scalarmul(&ext,sk);
    }
    when = now() - when;
    printf("edwards smz: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        scalarmul_vlook(&ext,sk);
    }
    when = now() - when;
    printf("edwards svl: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        scalarmul(&ext,sk);
        untwist_and_double_and_serialize(a,&ext);
    }
    when = now() - when;
    printf("edwards smc: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        q448_randomize(&crand, sk);
        scalarmul_vt(&ext,sk,SCALAR_BITS);
    }
    when = now() - when;
    printf("edwards vtm: %5.1fµs\n", when * 1e6 / i);
    
    tw_niels_a_t wnaft[1<<6];
    when = now();
    for (i=0; i<nbase/10; i++) {
        ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,6));
    }
    when = now() - when;
    printf("wnaf6 pre:   %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        q448_randomize(&crand, sk);
        scalarmul_fixed_base_wnaf_vt(&ext,sk,SCALAR_BITS,(const tw_niels_a_t*)wnaft,6);
    }
    when = now() - when;
    printf("edwards vt6: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,4));
    }
    when = now() - when;
    printf("wnaf4 pre:   %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        q448_randomize(&crand, sk);
        scalarmul_fixed_base_wnaf_vt(&ext,sk,SCALAR_BITS,(const tw_niels_a_t*)wnaft,4);
    }
    when = now() - when;
    printf("edwards vt4: %5.1fµs\n", when * 1e6 / i);

    when = now();
    for (i=0; i<nbase/10; i++) {
        ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,5));
    }
    when = now() - when;
    printf("wnaf5 pre:   %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        q448_randomize(&crand, sk);
        scalarmul_fixed_base_wnaf_vt(&ext,sk,SCALAR_BITS,(const tw_niels_a_t*)wnaft,5);
    }
    when = now() - when;
    printf("edwards vt5: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        q448_randomize(&crand, sk);
        q448_randomize(&crand, tk);
        linear_combo_var_fixed_vt(&ext,sk,FIELD_BITS,tk,FIELD_BITS,(const tw_niels_a_t*)wnaft,5);
    }
    when = now() - when;
    printf("vt vf combo: %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        deserialize_affine(&affine, a);
        convert_affine_to_extensible(&exta,&affine);
        twist_and_double(&ext,&exta);
        scalarmul(&ext,sk);
        untwist_and_double(&exta,&ext);
        serialize_extensible(b, &exta);
    }
    when = now() - when;
    printf("edwards sm:  %5.1fµs\n", when * 1e6 / i);
    
    struct fixed_base_table_t t_5_5_18, t_3_5_30, t_8_4_14, t_5_3_30, t_15_3_10;

    while (1) {
        field_randomize(&crand, a);
        if (deserialize_affine(&affine, a)) break;
    }
    convert_affine_to_extensible(&exta,&affine);
    twist_and_double(&ext,&exta);
    when = now();
    for (i=0; i<nbase/10; i++) {
        if (i) destroy_fixed_base(&t_5_5_18);
        ignore_result(precompute_fixed_base(&t_5_5_18, &ext, 5, 5, 18, NULL));
    }
    when = now() - when;
    printf("pre(5,5,18): %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        if (i) destroy_fixed_base(&t_3_5_30);
        ignore_result(precompute_fixed_base(&t_3_5_30, &ext, 3, 5, 30, NULL));
    }
    when = now() - when;
    printf("pre(3,5,30): %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        if (i) destroy_fixed_base(&t_5_3_30);
        ignore_result(precompute_fixed_base(&t_5_3_30, &ext, 5, 3, 30, NULL));
    }
    when = now() - when;
    printf("pre(5,3,30): %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        if (i) destroy_fixed_base(&t_15_3_10);
        ignore_result(precompute_fixed_base(&t_15_3_10, &ext, 15, 3, 10, NULL));
    }
    when = now() - when;
    printf("pre(15,3,10):%5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase/10; i++) {
        if (i) destroy_fixed_base(&t_8_4_14);
        ignore_result(precompute_fixed_base(&t_8_4_14, &ext, 8, 4, 14, NULL));
    }
    when = now() - when;
    printf("pre(8,4,14): %5.1fµs\n", when * 1e6 / i);
	
    when = now();
    for (i=0; i<nbase; i++) {
        scalarmul_fixed_base(&ext, sk, FIELD_BITS, &t_5_5_18);
    }
    when = now() - when;
    printf("com(5,5,18): %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase; i++) {
        scalarmul_fixed_base(&ext, sk, FIELD_BITS, &t_3_5_30);
    }
    when = now() - when;
    printf("com(3,5,30): %5.1fµs\n", when * 1e6 / i);

    when = now();
    for (i=0; i<nbase; i++) {
        scalarmul_fixed_base(&ext, sk, FIELD_BITS, &t_8_4_14);
    }
    when = now() - when;
    printf("com(8,4,14): %5.1fµs\n", when * 1e6 / i);

    when = now();
    for (i=0; i<nbase; i++) {
        scalarmul_fixed_base(&ext, sk, FIELD_BITS, &t_5_3_30);
    }
    when = now() - when;
    printf("com(5,3,30): %5.1fµs\n", when * 1e6 / i);

    when = now();
    for (i=0; i<nbase; i++) {
        scalarmul_fixed_base(&ext, sk, FIELD_BITS, &t_15_3_10);
    }
    when = now() - when;
    printf("com(15,3,10):%5.1fµs\n", when * 1e6 / i);
    
    printf("\nGoldilocks:\n");
    
    int res = goldilocks_init();
    assert(!res);
    
    struct goldilocks_public_key_t gpk,hpk;
    struct goldilocks_private_key_t gsk,hsk;
    
    when = now();
    for (i=0; i<nbase; i++) {
        if (i&1) {
            res = goldilocks_keygen(&gsk,&gpk);
        } else {
            res = goldilocks_keygen(&hsk,&hpk);
        }
        assert(!res);
    }
    when = now() - when;
    printf("keygen:      %5.1fµs\n", when * 1e6 / i);
    
    uint8_t ss1[64],ss2[64];
    int gres1=0,gres2=0;
    when = now();
    for (i=0; i<nbase; i++) {
        if (i&1) {
            gres1 = goldilocks_shared_secret(ss1,&gsk,&hpk);
        } else {
            gres2 = goldilocks_shared_secret(ss2,&hsk,&gpk);
        }
    }
    when = now() - when;
    printf("ecdh:        %5.1fµs\n", when * 1e6 / i);
    if (gres1 || gres2 || memcmp(ss1,ss2,64)) {
        printf("[FAIL] %d %d\n",gres1,gres2);
        
        printf("sk1 = ");
        for (i=0; i<SCALAR_BYTES; i++) {
            printf("%02x", gsk.opaque[i]);
        }
        printf("\nsk2 = ");
        for (i=0; i<SCALAR_BYTES; i++) {
            printf("%02x", hsk.opaque[i]);
        }
        printf("\nss1 = ");
        for (i=0; i<64; i++) {
            printf("%02x", ss1[i]);
        }
        printf("\nss2 = ");
        for (i=0; i<64; i++) {
            printf("%02x", ss2[i]);
        }
        printf("\n");
    }
    
    uint8_t sout[FIELD_BYTES*2];
    const char *message = "hello world";
    size_t message_len = strlen(message);
    when = now();
    for (i=0; i<nbase; i++) {
        res = goldilocks_sign(sout,(const unsigned char *)message,message_len,&gsk);
        (void)res;
        assert(!res);
    }
    when = now() - when;
    printf("sign:        %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase; i++) {
        int ver = goldilocks_verify(sout,(const unsigned char *)message,message_len,&gpk);
        (void)ver;
        assert(!ver);
    }
    when = now() - when;
    printf("verify:      %5.1fµs\n", when * 1e6 / i);
    
    struct goldilocks_precomputed_public_key_t *pre = NULL;
    when = now();
    for (i=0; i<nbase; i++) {
        goldilocks_destroy_precomputed_public_key(pre);
        pre = goldilocks_precompute_public_key(&gpk);
    }
    when = now() - when;
    printf("precompute:  %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase; i++) {
        int ver = goldilocks_verify_precomputed(sout,(const unsigned char *)message,message_len,pre);
        (void)ver;
        assert(!ver);
    }
    when = now() - when;
    printf("verify pre:  %5.1fµs\n", when * 1e6 / i);
    
    when = now();
    for (i=0; i<nbase; i++) {
        int ret = goldilocks_shared_secret_precomputed(ss1,&gsk,pre);
        (void)ret;
        assert(!ret);
    }
    when = now() - when;
    printf("ecdh pre:    %5.1fµs\n", when * 1e6 / i);
    
    printf("\nTesting...\n");
    
    
    int failures=0, successes = 0;
    for (i=0; i<nbase/10; i++) {
        ignore_result(goldilocks_keygen(&gsk,&gpk));
        goldilocks_sign(sout,(const unsigned char *)message,message_len,&gsk);
        res = goldilocks_verify(sout,(const unsigned char *)message,message_len,&gpk);
        if (res) failures++;
    }
    if (failures) {
        printf("FAIL %d/%d signature checks!\n", failures, i);
    }
    
    failures=0; successes = 0;
    for (i=0; i<nbase/10; i++) {
        field_randomize(&crand, a);
		word_t two = 2;
        mask_t good = montgomery_ladder(b,a,&two,2,0);
		if (!good) continue;
		
		word_t x,y;
        crandom_generate(&crand, (unsigned char *)&x, sizeof(x));
        crandom_generate(&crand, (unsigned char *)&y, sizeof(y));
        x = (hword_t)x;
        y = (hword_t)y;
        word_t z=x*y;
        
    	ignore_result(montgomery_ladder(b,a,&x,WORD_BITS,0));
        ignore_result(montgomery_ladder(c,b,&y,WORD_BITS,0));
        ignore_result(montgomery_ladder(b,a,&z,WORD_BITS,0));
        
        field_sub(d,b,c);
		if (!field_is_zero(d)) {
            printf("Odd ladder validation failure %d!\n", ++failures);
            field_print("a", a);
            printf("x=%"PRIxWORD", y=%"PRIxWORD", z=%"PRIxWORD"\n", x,y,z);
            field_print("c", c);
            field_print("b", b);
			printf("\n");
		}
	}
    
    failures = 0;
    for (i=0; i<nbase/10; i++) {
        mask_t good;
        do {
            field_randomize(&crand, a);
            good = deserialize_affine(&affine, a);
        } while (!good);
        
        convert_affine_to_extensible(&exta,&affine);
        twist_and_double(&ext,&exta);
        untwist_and_double(&exta,&ext);
        serialize_extensible(b, &exta);
        untwist_and_double_and_serialize(c, &ext);
        
        field_sub(d,b,c);
        
        if (good && !field_is_zero(d)){
            printf("Iso+serial validation failure %d!\n", ++failures);
            field_print("a", a);
            field_print("b", b);
            field_print("c", c);
            printf("\n");
        } else if (good) {
            successes ++;
        }
    }
    if (successes < i/3) {
        printf("Iso+serial variation: only %d/%d successful.\n", successes, i);
    }
    
    successes = failures = 0;
    for (i=0; i<nbase/10; i++) {
        field_a_t aa;
        struct tw_extensible_t exu,exv,exw;
        
        mask_t good;
        do {
            field_randomize(&crand, a);
            good = deserialize_affine(&affine, a);
            convert_affine_to_extensible(&exta,&affine);
            twist_and_double(&ext,&exta);
        } while (!good);
        do {
            field_randomize(&crand, aa);
            good = deserialize_affine(&affine, aa);
            convert_affine_to_extensible(&exta,&affine);
            twist_and_double(&exu,&exta);
        } while (!good);
        field_randomize(&crand, aa);
        
        q448_randomize(&crand, sk);
		if (i==0 || i==2) memset(&sk, 0, sizeof(sk));
        q448_randomize(&crand, tk);
		if (i==0 || i==1) memset(&tk, 0, sizeof(tk));
        
        copy_tw_extensible(&exv, &ext);
        copy_tw_extensible(&exw, &exu);
        scalarmul(&exv,sk);
        scalarmul(&exw,tk);
        convert_tw_extensible_to_tw_pniels(&pniels, &exw);
        add_tw_pniels_to_tw_extensible(&exv,&pniels);
        untwist_and_double(&exta,&exv);
        serialize_extensible(b, &exta);

        ignore_result(precompute_fixed_base_wnaf(wnaft,&exu,5));
        linear_combo_var_fixed_vt(&ext,sk,FIELD_BITS,tk,FIELD_BITS,(const tw_niels_a_t*)wnaft,5);
        untwist_and_double(&exta,&exv);
        serialize_extensible(c, &exta);
        
        field_sub(d,b,c);
        
        if (!field_is_zero(d)){
            printf("PreWNAF combo validation failure %d!\n", ++failures);
            field_print("a", a);
            field_print("A", aa);
            q448_print("s", sk);
            q448_print("t", tk);
            field_print("c", c);
            field_print("b", b);
            printf("\n\n");
        } else if (good) {
            successes ++;
        }
    }
    if (successes < i) {
        printf("PreWNAF combo variation: only %d/%d successful.\n", successes, i);
    }
    
    return 0;
}
bool protoshares_revalidateCollision(minerProtosharesBlock_t* block, uint8* midHash, uint32 indexA, uint32 indexB)
{
	//if( indexA > MAX_MOMENTUM_NONCE )
	//	printf("indexA out of range\n");
	//if( indexB > MAX_MOMENTUM_NONCE )
	//	printf("indexB out of range\n");
	//if( indexA == indexB )
	//	printf("indexA == indexB");
	uint8 tempHash[32+4];
	uint64 resultHash[8];
	memcpy(tempHash+4, midHash, 32);
	// get birthday A
	*(uint32*)tempHash = indexA&~7;
	sha512_ctx c512;
	sha512_init(&c512);
	sha512_update(&c512, tempHash, 32+4);
	sha512_final(&c512, (unsigned char*)resultHash);
	uint64 birthdayA = resultHash[indexA&7] >> (64ULL-SEARCH_SPACE_BITS);
	// get birthday B
	*(uint32*)tempHash = indexB&~7;
	sha512_init(&c512);
	sha512_update(&c512, tempHash, 32+4);
	sha512_final(&c512, (unsigned char*)resultHash);
	uint64 birthdayB = resultHash[indexB&7] >> (64ULL-SEARCH_SPACE_BITS);
	if( birthdayA != birthdayB )
	{
		false_positives++;
		return false; // invalid collision
	}
	// birthday collision found
	totalCollisionCount += 2; // we can use every collision twice -> A B and B A
	//printf("Collision found %8d = %8d | num: %d\n", indexA, indexB, totalCollisionCount);
	// get full block hash (for A B)
	block->birthdayA = indexA;
	block->birthdayB = indexB;
	uint8 proofOfWorkHash[32];
	sha256_ctx c256;
	sha256_init(&c256);
	sha256_update(&c256, (unsigned char*)block, 80+8);
	sha256_final(&c256, proofOfWorkHash);
	sha256_init(&c256);
	sha256_update(&c256, (unsigned char*)proofOfWorkHash, 32);
	sha256_final(&c256, proofOfWorkHash);
	bool hashMeetsTarget = true;
	uint32* generatedHash32 = (uint32*)proofOfWorkHash;
	uint32* targetHash32 = (uint32*)block->targetShare;
	for(sint32 hc=7; hc>=0; hc--)
	{
		if( generatedHash32[hc] < targetHash32[hc] )
		{
			hashMeetsTarget = true;
			break;
		}
		else if( generatedHash32[hc] > targetHash32[hc] )
		{
			hashMeetsTarget = false;
			break;
		}
	}
	if( hashMeetsTarget )
	{
		totalShareCount++;
		jhProtominer_submitShare(block);
	}
	// get full block hash (for B A)
	block->birthdayA = indexB;
	block->birthdayB = indexA;
	sha256_init(&c256);
	sha256_update(&c256, (unsigned char*)block, 80+8);
	sha256_final(&c256, proofOfWorkHash);
	sha256_init(&c256);
	sha256_update(&c256, (unsigned char*)proofOfWorkHash, 32);
	sha256_final(&c256, proofOfWorkHash);
	hashMeetsTarget = true;
	generatedHash32 = (uint32*)proofOfWorkHash;
	targetHash32 = (uint32*)block->targetShare;
	for(sint32 hc=7; hc>=0; hc--)
	{
		if( generatedHash32[hc] < targetHash32[hc] )
		{
			hashMeetsTarget = true;
			break;
		}
		else if( generatedHash32[hc] > targetHash32[hc] )
		{
			hashMeetsTarget = false;
			break;
		}
	}
	if( hashMeetsTarget )
	{
		totalShareCount++;
		jhProtominer_submitShare(block);
	}
	return true;
}