Esempio n. 1
0
HmacSha256Key
PeerAuth::getSendingMacKey(Curve25519Public const& remotePublic,
                           uint256 const& localNonce,
                           uint256 const& remoteNonce, Peer::PeerRole role)
{
    std::vector<uint8_t> buf;
    if (role == Peer::WE_CALLED_REMOTE)
    {
        // If WE_CALLED_REMOTE then sending key is K_AB,
        // and A is local and B is remote.
        buf.push_back(0);
        buf.insert(buf.end(), localNonce.begin(), localNonce.end());
        buf.insert(buf.end(), remoteNonce.begin(), remoteNonce.end());
    }
    else
    {
        // If REMOTE_CALLED_US then sending key is K_BA,
        // and B is local and A is remote.
        buf.push_back(1);
        buf.insert(buf.end(), localNonce.begin(), localNonce.end());
        buf.insert(buf.end(), remoteNonce.begin(), remoteNonce.end());
    }
    auto k = getSharedKey(remotePublic, role);
    return hkdfExpand(k, buf);
}
Esempio n. 2
0
uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
    const uint256& randomSeed,
    const boost::array<uint256, NumInputs>& nullifiers,
    const uint256& pubKeyHash
) {
    const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES]
        = {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'};

    std::vector<unsigned char> block(randomSeed.begin(), randomSeed.end());

    for (size_t i = 0; i < NumInputs; i++) {
        block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end());
    }

    block.insert(block.end(), pubKeyHash.begin(), pubKeyHash.end());

    uint256 output;

    if (crypto_generichash_blake2b_salt_personal(output.begin(), 32,
                                                 &block[0], block.size(),
                                                 NULL, 0, // No key.
                                                 NULL,    // No salt.
                                                 personalization
                                                ) != 0)
    {
        throw std::logic_error("hash function failure");
    }

    return output;
}
Esempio n. 3
0
 uint32_t operator()(const uint256& key) const
 {
     static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available.");
     uint32_t u;
     std::memcpy(&u, key.begin() + 4 * hash_select, 4);
     return u;
 }
Esempio n. 4
0
std::array<unsigned char, 11> default_diversifier(const uint256& sk)
{
    std::array<unsigned char, 11> res;   
    unsigned char blob[34];

    memcpy(&blob[0], sk.begin(), 32);
    blob[32] = 3;
    
    blob[33] = 0;
    while (true) {
        crypto_generichash_blake2b_state state;
        crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION);
        crypto_generichash_blake2b_update(&state, blob, 34);
        crypto_generichash_blake2b_final(&state, res.data(), 11);
        
        if (librustzcash_check_diversifier(res.data())) {
            break;
        } else if (blob[33] == 255) {
            throw std::runtime_error("librustzcash_check_diversifier did not return valid diversifier");
        }
        blob[33] += 1;
    }
        
    return res;
}
Esempio n. 5
0
// Which branch would contain the specified hash
int SHAMapNodeID::selectBranch (uint256 const& hash) const
{
#if RIPPLE_VERIFY_NODEOBJECT_KEYS

    if (mDepth >= 64)
    {
        assert (false);
        return -1;
    }

    if ((hash & Masks(mDepth)) != mNodeID)
    {
        std::cerr << "selectBranch(" << getString () << std::endl;
        std::cerr << "  " << hash << " off branch" << std::endl;
        assert (false);
        return -1;  // does not go under this node
    }

#endif

    int branch = * (hash.begin () + (mDepth / 2));

    if (mDepth & 1)
        branch &= 0xf;
    else
        branch >>= 4;

    assert ((branch >= 0) && (branch < 16));

    return branch;
}
Esempio n. 6
0
std::uint64_t ProofOfWork::getDifficulty (uint256 const& target, int iterations)
{
    // calculate the approximate number of hashes required to solve this proof of work
    if ((iterations > kMaxIterations) || (target < sMinTarget))
    {
        WriteLog (lsINFO, ProofOfWork) << "Iterations:" << iterations;
        WriteLog (lsINFO, ProofOfWork) << "MaxIterat: " << kMaxIterations;
        WriteLog (lsINFO, ProofOfWork) << "Target:    " << target;
        WriteLog (lsINFO, ProofOfWork) << "MinTarget: " << sMinTarget;
        throw std::runtime_error ("invalid proof of work target/iteration");
    }

    // more iterations means more hashes per iteration but also a larger final hash
    std::uint64_t difficulty = iterations + (iterations / 8);

    // Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty
    const unsigned char* ptr = target.begin ();

    while (*ptr == 0)
    {
        difficulty *= 256;
        ++ptr;
    }

    difficulty = (difficulty * 256) / (*ptr + 1);

    return difficulty;
}
Esempio n. 7
0
std::vector<std::pair<arith_uint256, CDeterministicMNCPtr>> CDeterministicMNList::CalculateScores(const uint256& modifier) const
{
    std::vector<std::pair<arith_uint256, CDeterministicMNCPtr>> scores;
    scores.reserve(GetAllMNsCount());
    ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) {
        if (dmn->pdmnState->confirmedHash.IsNull()) {
            // we only take confirmed MNs into account to avoid hash grinding on the ProRegTxHash to sneak MNs into a
            // future quorums
            return;
        }
        // calculate sha256(sha256(proTxHash, confirmedHash), modifier) per MN
        // Please note that this is not a double-sha256 but a single-sha256
        // The first part is already precalculated (confirmedHashWithProRegTxHash)
        // TODO When https://github.com/bitcoin/bitcoin/pull/13191 gets backported, implement something that is similar but for single-sha256
        uint256 h;
        CSHA256 sha256;
        sha256.Write(dmn->pdmnState->confirmedHashWithProRegTxHash.begin(), dmn->pdmnState->confirmedHashWithProRegTxHash.size());
        sha256.Write(modifier.begin(), modifier.size());
        sha256.Finalize(h.begin());

        scores.emplace_back(UintToArith256(h), dmn);
    });

    return scores;
}
bool CZMQPublishHashBlockNotifier::NotifyBlock(const uint256 &hash)
{
    LogPrint("zmq", "Publish hash block %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0);
    return rc == 0;
}
Esempio n. 9
0
void RippleAddress::sign(uint256 const& message, Blob& retSignature) const
{
	assert(vchData.size() == 64);

	const unsigned char *key = vchData.data();
	retSignature.resize(crypto_sign_BYTES);
	crypto_sign_detached(&retSignature[0], NULL,
		(unsigned char*)message.begin(), message.size(),
		key);
}
Esempio n. 10
0
int PrimeWorker::CheckReqNonce(const uint256& nonce) {
	
	const uint32_t* limbs = (uint32_t*)nonce.begin();
	
	uint32_t tmp = limbs[0];
	for(int i = 1; i < 7; ++i)
		tmp *= limbs[i];
	tmp += limbs[7];
	
	return !tmp;
	
}
Esempio n. 11
0
	void PaysharesPrivateKey::sign(uint256 const& message, Blob& retSignature) const
	{
		unsigned char out[crypto_sign_BYTES + message.bytes];
		unsigned long long len;
		const unsigned char *key = mPair.mPrivateKey.data();

		// contrary to the docs it puts the signature in front
		crypto_sign(out, &len,
			(unsigned char*)message.begin(), message.size(),
			key);

		retSignature.resize(crypto_sign_BYTES);
		memcpy(&retSignature[0], out, crypto_sign_BYTES);
	}
Esempio n. 12
0
// Sapling 
std::array<unsigned char, 64> PRF_expand(const uint256& sk, unsigned char t)
{
    std::array<unsigned char, 64> res;   
    unsigned char blob[33];

    memcpy(&blob[0], sk.begin(), 32);
    blob[32] = t;
        
    crypto_generichash_blake2b_state state;
    crypto_generichash_blake2b_init_salt_personal(&state, nullptr, 0, 64, nullptr, ZCASH_EXPANDSEED_PERSONALIZATION);
    crypto_generichash_blake2b_update(&state, blob, 33);
    crypto_generichash_blake2b_final(&state, res.data(), 64);
    
    return res;
}
Esempio n. 13
0
void dumpKeyInfo(uint256 secret)
{
    CKey key;
    CAnoncoinSecret b58secret;
    printf("  * secret (hex): %s\n", secret.GetHex().c_str());
    for (int nCompressed=0; nCompressed<2; nCompressed++)
    {
        bool fCompressed = nCompressed == 1;
        printf("  * %s:\n", fCompressed ? "compressed" : "uncompressed");
        key.Set( secret.begin(), secret.end(), fCompressed );
        b58secret.SetKey( key );
        printf("    * secret (base58): %s\n", b58secret.ToString().c_str());
        CPubKey pubkey = key.GetPubKey();
        printf("    * address (base58): %s\n", CAnoncoinAddress(CTxDestination(pubkey.GetID())).ToString().c_str() );
    }
}
Esempio n. 14
0
// Sprout
uint256 PRF(bool a, bool b, bool c, bool d,
            const uint252& x,
            const uint256& y)
{
    uint256 res;
    unsigned char blob[64];

    memcpy(&blob[0], x.begin(), 32);
    memcpy(&blob[32], y.begin(), 32);

    blob[0] &= 0x0F;
    blob[0] |= (a ? 1 << 7 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 5 : 0) | (d ? 1 << 4 : 0);

    CSHA256 hasher;
    hasher.Write(blob, 64);
    hasher.FinalizeNoPadding(res.begin());

    return res;
}
Esempio n. 15
0
ec_key ECDSAPrivateKey (uint256 const& serialized)
{
    BIGNUM* bn = BN_bin2bn (serialized.begin(), serialized.size(), nullptr);

    if (bn == nullptr)
    {
        throw std::runtime_error ("ec_key::ec_key: BN_bin2bn failed");
    }

    EC_KEY* key = new_initialized_EC_KEY();

    const bool ok = EC_KEY_set_private_key (key, bn);

    BN_clear_free (bn);

    if (! ok)
    {
        EC_KEY_free (key);
    }

    return ec_key::acquire ((ec_key::pointer_t) key);
}
Esempio n. 16
0
void
CAuxPow::initAuxPow (CBlockHeader& header)
{
  /* Set auxpow flag right now, since we take the block hash below.  */
  header.SetAuxpowVersion(true);

  /* Build a minimal coinbase script input for merge-mining.  */
  const uint256 blockHash = header.GetHash ();
  valtype inputData(blockHash.begin (), blockHash.end ());
  std::reverse (inputData.begin (), inputData.end ());
  inputData.push_back (1);
  inputData.insert (inputData.end (), 7, 0);

  /* Fake a parent-block coinbase with just the required input
     script and no outputs.  */
  CMutableTransaction coinbase;
  coinbase.vin.resize (1);
  coinbase.vin[0].prevout.SetNull ();
  coinbase.vin[0].scriptSig = (CScript () << inputData);
  assert (coinbase.vout.empty ());
  CTransactionRef coinbaseRef = MakeTransactionRef (coinbase);

  /* Build a fake parent block with the coinbase.  */
  CBlock parent;
  parent.nVersion = 1;
  parent.vtx.resize (1);
  parent.vtx[0] = coinbaseRef;
  parent.hashMerkleRoot = BlockMerkleRoot (parent);

  /* Construct the auxpow object.  */
  header.SetAuxpow (new CAuxPow (coinbaseRef));
  assert (header.auxpow->vChainMerkleBranch.empty ());
  header.auxpow->nChainIndex = 0;
  assert (header.auxpow->vMerkleBranch.empty ());
  header.auxpow->nIndex = 0;
  header.auxpow->parentBlock = parent;
}
Esempio n. 17
0
void RippleAddress::setAccountPrivate(uint256 hash256)
{
    SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32);
}
Esempio n. 18
0
void RippleAddress::setNodePrivate(uint256 hash256)
{
    SetData(VER_NODE_PRIVATE, hash256.begin(), 32);
}
Esempio n. 19
0
bool
CAuxPow::check (const uint256& hashAuxBlock, int nChainId,
                const Consensus::Params& params) const
{
    if (nIndex != 0)
        return error("AuxPow is not a generate");

    if (params.fStrictChainId && parentBlock.GetChainId () == nChainId)
        return error("Aux POW parent has our chain ID");

    if (vChainMerkleBranch.size() > 30)
        return error("Aux POW chain merkle branch too long");

    // Check that the chain merkle root is in the coinbase
    const uint256 nRootHash
      = CheckMerkleBranch (hashAuxBlock, vChainMerkleBranch, nChainIndex);
    valtype vchRootHash(nRootHash.begin (), nRootHash.end ());
    std::reverse (vchRootHash.begin (), vchRootHash.end ()); // correct endian

    // Check that we are in the parent block merkle tree
    if (CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex)
          != parentBlock.hashMerkleRoot)
        return error("Aux POW merkle root incorrect");

    const CScript script = tx->vin[0].scriptSig;

    // Check that the same work is not submitted twice to our chain.
    //

    CScript::const_iterator pcHead =
        std::search(script.begin(), script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader));

    CScript::const_iterator pc =
        std::search(script.begin(), script.end(), vchRootHash.begin(), vchRootHash.end());

    if (pc == script.end())
        return error("Aux POW missing chain merkle root in parent coinbase");

    if (pcHead != script.end())
    {
        // Enforce only one chain merkle root by checking that a single instance of the merged
        // mining header exists just before.
        if (script.end() != std::search(pcHead + 1, script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader)))
            return error("Multiple merged mining headers in coinbase");
        if (pcHead + sizeof(pchMergedMiningHeader) != pc)
            return error("Merged mining header is not just before chain merkle root");
    }
    else
    {
        // For backward compatibility.
        // Enforce only one chain merkle root by checking that it starts early in the coinbase.
        // 8-12 bytes are enough to encode extraNonce and nBits.
        if (pc - script.begin() > 20)
            return error("Aux POW chain merkle root must start in the first 20 bytes of the parent coinbase");
    }


    // Ensure we are at a deterministic point in the merkle leaves by hashing
    // a nonce and our chain ID and comparing to the index.
    pc += vchRootHash.size();
    if (script.end() - pc < 8)
        return error("Aux POW missing chain merkle tree size and nonce in parent coinbase");

    uint32_t nSize;
    memcpy(&nSize, &pc[0], 4);
    nSize = le32toh (nSize);
    const unsigned merkleHeight = vChainMerkleBranch.size ();
    if (nSize != (1u << merkleHeight))
        return error("Aux POW merkle branch size does not match parent coinbase");

    uint32_t nNonce;
    memcpy(&nNonce, &pc[4], 4);
    nNonce = le32toh (nNonce);
    if (nChainIndex != getExpectedIndex (nNonce, nChainId, merkleHeight))
        return error("Aux POW wrong index");

    return true;
}
Esempio n. 20
0
/** insecure_GetRandHash fills in a uint256 from insecure_rand
 */
void insecure_GetRandHash(uint256& t)
{
    uint32_t* ptr = (uint32_t*)t.begin();
    for (uint8_t j = 0; j < 8; ++j)
        *(ptr++) = insecure_rand.rand32();
}
Esempio n. 21
0
    SproutProof prove(
        bool makeGrothProof,
        const std::array<JSInput, NumInputs>& inputs,
        const std::array<JSOutput, NumOutputs>& outputs,
        std::array<SproutNote, NumOutputs>& out_notes,
        std::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
        uint256& out_ephemeralKey,
        const uint256& joinSplitPubKey,
        uint256& out_randomSeed,
        std::array<uint256, NumInputs>& out_macs,
        std::array<uint256, NumInputs>& out_nullifiers,
        std::array<uint256, NumOutputs>& out_commitments,
        uint64_t vpub_old,
        uint64_t vpub_new,
        const uint256& rt,
        bool computeProof,
        uint256 *out_esk // Payment disclosure
    ) {
        if (vpub_old > MAX_MONEY) {
            throw std::invalid_argument("nonsensical vpub_old value");
        }

        if (vpub_new > MAX_MONEY) {
            throw std::invalid_argument("nonsensical vpub_new value");
        }

        uint64_t lhs_value = vpub_old;
        uint64_t rhs_value = vpub_new;

        for (size_t i = 0; i < NumInputs; i++) {
            // Sanity checks of input
            {
                // If note has nonzero value
                if (inputs[i].note.value() != 0) {
                    // The witness root must equal the input root.
                    if (inputs[i].witness.root() != rt) {
                        throw std::invalid_argument("joinsplit not anchored to the correct root");
                    }

                    // The tree must witness the correct element
                    if (inputs[i].note.cm() != inputs[i].witness.element()) {
                        throw std::invalid_argument("witness of wrong element for joinsplit input");
                    }
                }

                // Ensure we have the key to this note.
                if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) {
                    throw std::invalid_argument("input note not authorized to spend with given key");
                }

                // Balance must be sensical
                if (inputs[i].note.value() > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical input note value");
                }

                lhs_value += inputs[i].note.value();

                if (lhs_value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical left hand size of joinsplit balance");
                }
            }

            // Compute nullifier of input
            out_nullifiers[i] = inputs[i].nullifier();
        }

        // Sample randomSeed
        out_randomSeed = random_uint256();

        // Compute h_sig
        uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, joinSplitPubKey);

        // Sample phi
        uint252 phi = random_uint252();

        // Compute notes for outputs
        for (size_t i = 0; i < NumOutputs; i++) {
            // Sanity checks of output
            {
                if (outputs[i].value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical output value");
                }

                rhs_value += outputs[i].value;

                if (rhs_value > MAX_MONEY) {
                    throw std::invalid_argument("nonsensical right hand side of joinsplit balance");
                }
            }

            // Sample r
            uint256 r = random_uint256();

            out_notes[i] = outputs[i].note(phi, r, i, h_sig);
        }

        if (lhs_value != rhs_value) {
            throw std::invalid_argument("invalid joinsplit balance");
        }

        // Compute the output commitments
        for (size_t i = 0; i < NumOutputs; i++) {
            out_commitments[i] = out_notes[i].cm();
        }

        // Encrypt the ciphertexts containing the note
        // plaintexts to the recipients of the value.
        {
            ZCNoteEncryption encryptor(h_sig);

            for (size_t i = 0; i < NumOutputs; i++) {
                SproutNotePlaintext pt(out_notes[i], outputs[i].memo);

                out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc);
            }

            out_ephemeralKey = encryptor.get_epk();

            // !!! Payment disclosure START
            if (out_esk != nullptr) {
                *out_esk = encryptor.get_esk();
            }
            // !!! Payment disclosure END
        }

        // Authenticate h_sig with each of the input
        // spending keys, producing macs which protect
        // against malleability.
        for (size_t i = 0; i < NumInputs; i++) {
            out_macs[i] = PRF_pk(inputs[i].key, i, h_sig);
        }

        if (makeGrothProof) {
            if (!computeProof) {
                return GrothProof();
            }

            GrothProof proof;

            CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION);
            ss1 << inputs[0].witness.path();
            std::vector<unsigned char> auth1(ss1.begin(), ss1.end());

            CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
            ss2 << inputs[1].witness.path();
            std::vector<unsigned char> auth2(ss2.begin(), ss2.end());

            librustzcash_sprout_prove(
                proof.begin(),

                phi.begin(),
                rt.begin(),
                h_sig.begin(),

                inputs[0].key.begin(),
                inputs[0].note.value(),
                inputs[0].note.rho.begin(),
                inputs[0].note.r.begin(),
                auth1.data(),

                inputs[1].key.begin(),
                inputs[1].note.value(),
                inputs[1].note.rho.begin(),
                inputs[1].note.r.begin(),
                auth2.data(),

                out_notes[0].a_pk.begin(),
                out_notes[0].value(),
                out_notes[0].r.begin(),

                out_notes[1].a_pk.begin(),
                out_notes[1].value(),
                out_notes[1].r.begin(),

                vpub_old,
                vpub_new
            );

            return proof;
        }

        if (!computeProof) {
            return PHGRProof();
        }

        protoboard<FieldT> pb;
        {
            joinsplit_gadget<FieldT, NumInputs, NumOutputs> g(pb);
            g.generate_r1cs_constraints();
            g.generate_r1cs_witness(
                phi,
                rt,
                h_sig,
                inputs,
                out_notes,
                vpub_old,
                vpub_new
            );
        }

        // The constraint system must be satisfied or there is an unimplemented
        // or incorrect sanity check above. Or the constraint system is broken!
        assert(pb.is_satisfied());

        // TODO: These are copies, which is not strictly necessary.
        std::vector<FieldT> primary_input = pb.primary_input();
        std::vector<FieldT> aux_input = pb.auxiliary_input();

        // Swap A and B if it's beneficial (less arithmetic in G2)
        // In our circuit, we already know that it's beneficial
        // to swap, but it takes so little time to perform this
        // estimate that it doesn't matter if we check every time.
        pb.constraint_system.swap_AB_if_beneficial();

        std::ifstream fh(pkPath, std::ios::binary);

        if(!fh.is_open()) {
            throw std::runtime_error(strprintf("could not load param file at %s", pkPath));
        }

        return PHGRProof(r1cs_ppzksnark_prover_streaming<ppzksnark_ppT>(
            fh,
            primary_input,
            aux_input,
            pb.constraint_system
        ));
    }