/* Combine stop 64-bits from each hash into a single hash */ inline uint256 CombineHashes(uint256 hash1, uint512 hash2, uint512 hash3, uint512 hash4) { uint256 mask = uint256("0x8000000000000000000000000000000000000000000000000000000000000000"); uint256 hash[4] = { hash1, hash2.trim256(), hash3.trim256(), hash4.trim256() }; /* Transpose first 64 bits of each hash into final */ uint256 final = 0; for (unsigned int i = 0; i < 64; i++) { for (unsigned int j = 0; j < 4; j++) { final <<= 1; if ((hash[j] & mask) != 0) final |= 1; } mask >>= 1; }
/* Combines top 64-bits from each hash into a single hash */ void CombineHashes(uint256& out, uint256 hash1, uint512 hash2, uint512 hash3, uint512 hash4) { uint256 mask = uint256("0x8000000000000000000000000000000000000000000000000000000000000000"); uint256 hash[4] = { hash1, hash2.trim256(), hash3.trim256(), hash4.trim256() }; /* Transpose first 64 bits of each hash into out */ out = 0; for (unsigned int i = 0; i < 64; i++) { for (unsigned int j = 0; j < 4; j++) { out <<= 1; if ((hash[j] & mask) != 0) out |= 1; } mask >>= 1; } }
void CzPIVWallet::SeedToZPIV(const uint512& seedZerocoin, CBigNum& bnValue, CBigNum& bnSerial, CBigNum& bnRandomness, CKey& key) { ZerocoinParams* params = Params().Zerocoin_Params(false); //convert state seed into a seed for the private key uint256 nSeedPrivKey = seedZerocoin.trim256(); bool isValidKey = false; key = CKey(); while (!isValidKey) { nSeedPrivKey = Hash(nSeedPrivKey.begin(), nSeedPrivKey.end()); isValidKey = libzerocoin::GenerateKeyPair(params->coinCommitmentGroup.groupOrder, nSeedPrivKey, key, bnSerial); } //hash randomness seed with Bottom 256 bits of seedZerocoin & attempts256 which is initially 0 uint256 randomnessSeed = uint512(seedZerocoin >> 256).trim256(); uint256 hashRandomness = Hash(randomnessSeed.begin(), randomnessSeed.end()); bnRandomness.setuint256(hashRandomness); bnRandomness = bnRandomness % params->coinCommitmentGroup.groupOrder; //See if serial and randomness make a valid commitment // Generate a Pedersen commitment to the serial number CBigNum commitmentValue = params->coinCommitmentGroup.g.pow_mod(bnSerial, params->coinCommitmentGroup.modulus).mul_mod( params->coinCommitmentGroup.h.pow_mod(bnRandomness, params->coinCommitmentGroup.modulus), params->coinCommitmentGroup.modulus); CBigNum random; uint256 attempts256 = 0; // Iterate on Randomness until a valid commitmentValue is found while (true) { // Now verify that the commitment is a prime number // in the appropriate range. If not, we'll throw this coin // away and generate a new one. if (IsValidCoinValue(commitmentValue)) { bnValue = commitmentValue; return; } //Did not create a valid commitment value. //Change randomness to something new and random and try again attempts256++; hashRandomness = Hash(randomnessSeed.begin(), randomnessSeed.end(), attempts256.begin(), attempts256.end()); random.setuint256(hashRandomness); bnRandomness = (bnRandomness + random) % params->coinCommitmentGroup.groupOrder; commitmentValue = commitmentValue.mul_mod(params->coinCommitmentGroup.h.pow_mod(random, params->coinCommitmentGroup.modulus), params->coinCommitmentGroup.modulus); } }