Exemplo n.º 1
0
HashType generate_hmac(const data_chunk& key, const data_chunk& data,
    std::function<HashType (const data_chunk&)> hash_func)
{
    typedef typename HashType::value_type hash_char;
    std::array<hash_char, block_size> fixed_key;
    // Zero out
    std::fill(fixed_key.begin(), fixed_key.end(), 0);
    // Now copy key or hash into zeroed out buffer
    if (key.size() <= block_size)
    {
        std::copy(key.begin(), key.end(), fixed_key.begin());
    }
    else
    {
        HashType fixed_key_digest = hash_func(key);
        BITCOIN_ASSERT(fixed_key.size() >= fixed_key_digest.size());
        std::copy(fixed_key_digest.begin(), fixed_key_digest.end(),
            fixed_key.begin());
    }
    // hash(o_key_pad + hash(i_key_pad + data))
    // Work on inner section first
    data_chunk inner_data(fixed_key.size() + data.size());
    // xor each digit of key...
    std::transform(fixed_key.begin(), fixed_key.end(), inner_data.begin(),
        [](hash_char digit) { return digit ^ 0x36; });
    // ... and append the data.
    std::copy(data.begin(), data.end(),
        inner_data.begin() + fixed_key.size());
    HashType inner_hash = hash_func(inner_data);
    // Work on outer section
    data_chunk outer_data(fixed_key.size() + inner_hash.size());
    // xor each digit of key...
    std::transform(fixed_key.begin(), fixed_key.end(), outer_data.begin(),
        [](hash_char digit) { return digit ^ 0x5c; });
    // ... and combine with inner_hash to get outer_data.
    std::copy(inner_hash.begin(), inner_hash.end(),
        outer_data.begin() + fixed_key.size());
    return hash_func(outer_data);
}
Exemplo n.º 2
0
void BIO::WriteWithRetry(const data_chunk& data2wr) const
{
	unsigned int written = 0;
	do {
		try {
			data_chunk tmp;
			tmp.insert(tmp.end(), data2wr.begin() + written, data2wr.end());
			written += doWrite(tmp, written);
		} catch (RecoverableException& ex) {

		}
	} while (written < data2wr.size());
}
Exemplo n.º 3
0
void push_data(data_chunk& raw_script, const data_chunk& data)
{
    operation op;
    // pushdata1 = 76
    if (data.empty())
        op.code = opcode::zero;
    else if (data.size() < 76)
        op.code = opcode::special;
    else if (data.size() <= 0xff)
        op.code = opcode::pushdata1;
    else if (data.size() <= 0xffff)
        op.code = opcode::pushdata2;
    else
    {
        BITCOIN_ASSERT(data.size() <= 0xffffffff);
        op.code = opcode::pushdata4;
    }
    op.data = data;
    script tmp_script;
    tmp_script.push_operation(op);
    extend_data(raw_script, save_script(tmp_script));
}
Exemplo n.º 4
0
int main(int argc, char** argv)
{
    if (argc != 4)
    {
        std::cerr << "Usage: pp_unlock CHUNKFILE BLOCK_HASH PUBKEY"
            << std::endl;
        return -1;
    }
    const std::string chunk_filename = argv[1];
    const data_chunk hash = decode_hex(argv[2]);
    if (hash.empty() || hash.size() != hash_size)
    {
        std::cerr << "pp_unlock: not a valid BLOCK_HASH." << std::endl;
        return -1;
    }
    const ec_point pubkey = decode_hex(argv[3]);
    if (pubkey.empty() || pubkey.size() != ec_compressed_size)
    {
        std::cerr << "pp_unlock: not a valid PUBKEY." << std::endl;
        return -1;
    }
    std::ifstream infile(chunk_filename, std::ifstream::binary);
    infile.seekg(0, std::ifstream::end);
    size_t file_size = infile.tellg();
    BITCOIN_ASSERT(file_size % 16 == 0);
    infile.seekg(0, std::ifstream::beg);
    // Read entire file in.
    data_chunk cipher(file_size);
    // Copy chunk to public chunk file.
    char* data = reinterpret_cast<char*>(cipher.data());
    infile.read(data, file_size);
    infile.close();
    // Get seed.
    payment_address bid_addr = bidding_address(pubkey);
    hash_digest seed = derive_seed(pubkey);
    // Decrypt chunk.
    aes256_context ctx; 
    BITCOIN_ASSERT(seed.size() == 32);
    aes256_init(&ctx, seed.data());
    BITCOIN_ASSERT(cipher.size() % 16 == 0);
    for (size_t i = 0; i < cipher.size(); i += 16)
        aes256_decrypt_ecb(&ctx, cipher.data() + i);
    aes256_done(&ctx);
    // Write out.
    const fs::path new_chunk_filename = (chunk_filename + ".decrypted");
    std::ofstream outfile(new_chunk_filename.native(), std::ifstream::binary);
    char* dec_data = reinterpret_cast<char*>(cipher.data());
    outfile.write(dec_data, cipher.size());
    return 0;
}
Exemplo n.º 5
0
int mmr_lookup(const data_chunk& key_data, const size_t value_size,
    const std::string& map_filename, const std::string& rows_filename)
{
    typedef byte_array<KeySize> hash_type;

    hash_type key;
    BITCOIN_ASSERT(key.size() == key_data.size());
    std::copy(key_data.begin(), key_data.end(), key.begin());

    memory_map ht_file(map_filename);
    BITCOIN_ASSERT(ht_file.open());

    record_hash_table_header header(ht_file, buckets);
    auto result = header.start();
    BITCOIN_ASSERT(result);

    const auto record_size = hash_table_multimap_record_size<hash_type>();
    BITCOIN_ASSERT(record_size == KeySize + 4 + 4);
    const auto header_size = record_hash_table_header_size(header.size());
    const file_offset records_start = header_size;

    record_manager ht_manager(ht_file, records_start, record_size);
    result = ht_manager.start();
    BITCOIN_ASSERT(result);

    memory_map lrs_file(rows_filename);
    BITCOIN_ASSERT(lrs_file.open());

    const auto lrs_record_size = record_list_offset + value_size;
    record_manager lrs_manager(lrs_file, 0, lrs_record_size);
    result = lrs_manager.start();
    BITCOIN_ASSERT(result);

    record_list lrs(lrs_manager);
    record_hash_table<hash_type> ht(header, ht_manager);
    record_multimap<hash_type> multimap(ht, lrs);
    record_multimap_iterable container(lrs, multimap.lookup(key));

    for (const array_index index: container)
    {
        std::cout << "Index: " << index << std::endl;
        const auto memory = lrs_manager.get(index);
        const auto record = REMAP_ADDRESS(memory) + record_list_offset;
        const data_chunk data(record, record + value_size);
        std::cout << encode_base16(data) << std::endl;
        std::cout << std::endl;
    }

    return 0;
}
Exemplo n.º 6
0
		bool payment_address::set_encoded(const std::string& encoded_address)
		{
			if (!is_base58(encoded_address))
				return false;
			const data_chunk decoded_address = decode_base58(encoded_address);
			// version + 20 bytes short hash + 4 bytes checksum
			if (decoded_address.size() != 25)
				return false;
			if (!verify_checksum(decoded_address))
				return false;

			version_ = decoded_address[0];
			std::copy_n(decoded_address.begin() + 1, hash_.size(), hash_.begin());
			return true;
		}
Exemplo n.º 7
0
std::string encode_base58(const data_chunk& unencoded_data)
{                                                                                
    std::string encoded_data;
    // Expected size increase from base58 conversion is approximately 137%
    // use 138% to be safe
    encoded_data.reserve((unencoded_data.size() - 1) * 138 / 100 + 1);

    // Convert big endian data to little endian
    // Extra zero at the end make sure bignum will interpret
    // as a positive number
    data_chunk tmp_data(unencoded_data.size() + 1, 0);
    std::reverse_copy(unencoded_data.begin(), unencoded_data.end(),
        tmp_data.begin());

    big_number long_value;
    long_value.set_data(tmp_data);
    while (long_value > 0)
    {                                                                            
        auto result = divmod(long_value, 58);
        long_value = result.first;
        size_t remainder = result.second.uint32();
        encoded_data += base58_chars[remainder];
    }                                                                            
                                                                                 
    // Leading zeroes encoded as base58 zeros                                    
    for (const uint8_t unencoded_byte: unencoded_data)
    {
        if (unencoded_byte != 0)
            break;
        encoded_data += base58_chars[0];
    }

    // Convert little endian std::string to big endian
    reverse(encoded_data.begin(), encoded_data.end());
    return encoded_data;
}                                                                                
Exemplo n.º 8
0
void AppendChecksum(data_chunk& data)
{
    uint32_t checksum = BitcoinChecksum(&data[0], data.size());
    
    // -- to_little_endian
    std::vector<uint8_t> tmp(4);
    
    //memcpy(&tmp[0], &checksum, 4);
    for (int i = 0; i < 4; ++i)
    {
        tmp[i] = checksum & 0xFF;
        checksum >>= 8;
    };
    
    data.insert(data.end(), tmp.begin(), tmp.end());
};
Exemplo n.º 9
0
short_hash generate_ripemd_hash(const data_chunk& chunk)
{
    hash_digest sha_hash;
    SHA256_CTX sha_ctx;
    SHA256_Init(&sha_ctx);
    SHA256_Update(&sha_ctx, &chunk[0], chunk.size());
    SHA256_Final(sha_hash.data(), &sha_ctx);

    short_hash ripemd_hash;
    RIPEMD160_CTX ripemd_ctx;
    RIPEMD160_Init(&ripemd_ctx);
    RIPEMD160_Update(&ripemd_ctx, sha_hash.data(), SHA256_DIGEST_LENGTH);
    RIPEMD160_Final(ripemd_hash.data(), &ripemd_ctx);

    return ripemd_hash;
}
Exemplo n.º 10
0
void proxy::do_send(const data_chunk& message, handler handler,
    const std::string& command)
{
    if (stopped())
    {
        handler(error::channel_stopped);
        return;
    }

    log_debug(LOG_NETWORK)
        << "Send " << command << " [" << address() << "] ("
        << message.size() << " bytes)";

    const shared_const_buffer buffer(message);
    async_write(*socket_, buffer,
        std::bind(&proxy::call_handle_send,
            shared_from_this(), _1, handler));
}
Exemplo n.º 11
0
bool payment_address::set_encoded(const std::string& encoded_address)
{
    const data_chunk decoded_address = decode_base58(encoded_address);
    // version + 20 bytes short hash + 4 bytes checksum
    if (decoded_address.size() != 25)
        return false;
    const uint8_t version = decoded_address[0];
    if (!set_version(version))
        return false;
    const data_chunk checksum_bytes(
        decoded_address.end() - 4, decoded_address.end());
    // version + short hash
    const data_chunk main_body(
        decoded_address.begin(), decoded_address.end() - 4);
    // verify checksum bytes
    if (generate_sha256_checksum(main_body) !=
            cast_chunk<uint32_t>(checksum_bytes))
        return false;
    std::copy(main_body.begin() + 1, main_body.end(), hash_.begin());
    return true;
}
Exemplo n.º 12
0
BCW_API bool hd_public_key::set_serialized(std::string encoded)
{
    if (!is_base58(encoded))
        return false;
    const data_chunk decoded = decode_base58(encoded);
    if (decoded.size() != serialized_length)
        return false;
    if (!verify_checksum(decoded))
        return false;

    auto ds = make_deserializer(decoded.begin(), decoded.end());
    auto prefix = ds.read_big_endian<uint32_t>();
    if (prefix != mainnet_public_prefix && prefix != testnet_public_prefix)
        return false;

    valid_ = true;
    lineage_.testnet = prefix == testnet_public_prefix;
    lineage_.depth = ds.read_byte();
    lineage_.parent_fingerprint = ds.read_little_endian<uint32_t>();
    lineage_.child_number = ds.read_big_endian<uint32_t>();
    c_ = ds.read_bytes<chain_code_size>();
    K_ = ds.read_data(33);
    return true;
}
Exemplo n.º 13
0
long_hash sha512_hash(const data_chunk& chunk)
{
    long_hash hash;
    SHA512__(chunk.data(), chunk.size(), hash.data());
    return hash;
}
Exemplo n.º 14
0
hash_digest sha256_hash(const data_chunk& chunk)
{
    hash_digest hash;
    SHA256__(chunk.data(), chunk.size(), hash.data());
    return hash;
}
Exemplo n.º 15
0
short_hash sha1_hash(const data_chunk& chunk)
{
    short_hash hash;
    SHA1(chunk.data(), chunk.size(), hash.data());
    return hash;
}
Exemplo n.º 16
0
short_hash ripemd160_hash(const data_chunk& chunk)
{
    short_hash hash;
    RMD160(chunk.data(), chunk.size(), hash.data());
    return hash;
}
Exemplo n.º 17
0
int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS)
{
    // https://bitcointalk.org/index.php?topic=972541.msg10619684

    // forall_{i=1..n} compute e_i=s_i*G+c_i*P_i and E_i=s_i*H(P_i)+c_i*I_j and c_{i+1}=h(P_1,...,P_n,e_i,E_i)
    // check c_{n+1}=c_1

    if (fDebugRingSig)
    {
        //LogPrintf("%s size %d\n", __func__, nRingSize); // happens often
    };

    if (sigC.size() != EC_SECRET_SIZE)
        return errorN(1, "%s: sigC size !=  EC_SECRET_SIZE.", __func__);
    if (keyImage.size() != EC_COMPRESSED_SIZE)
        return errorN(1, "%s: keyImage size !=  EC_COMPRESSED_SIZE.", __func__);

    int rv = 0;

    uint256 tmpPkHash;
    uint256 tmpHash;

    uint8_t tempData[66]; // hold raw point data to hash
    CHashWriter ssPkHash(SER_GETHASH, PROTOCOL_VERSION);
    CHashWriter ssCjHash(SER_GETHASH, PROTOCOL_VERSION);

    for (int i = 0; i < nRingSize; ++i)
    {
        ssPkHash.write((const char*)&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE);
    };

    tmpPkHash = ssPkHash.GetHash();

    BN_CTX_start(bnCtx);

    BIGNUM   *bnC  = BN_CTX_get(bnCtx);
    BIGNUM   *bnC1 = BN_CTX_get(bnCtx);
    BIGNUM   *bnT  = BN_CTX_get(bnCtx);
    BIGNUM   *bnS  = BN_CTX_get(bnCtx);
    EC_POINT *ptKi = NULL;
    EC_POINT *ptT1 = NULL;
    EC_POINT *ptT2 = NULL;
    EC_POINT *ptT3 = NULL;
    EC_POINT *ptPk = NULL;
    EC_POINT *ptSi = NULL;

    if (   !(ptKi = EC_POINT_new(ecGrp))
        || !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptSi = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!EC_POINT_oct2point(ecGrp, ptKi, &keyImage[0], EC_COMPRESSED_SIZE, bnCtx))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!bnC1 || !BN_bin2bn(&sigC[0], EC_SECRET_SIZE, bnC1))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_copy(bnC, bnC1))
    {
        LogPrintf("%s: BN_copy failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        if (!bnS || !(BN_bin2bn(&pSigS[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnS)))
        {
            LogPrintf("%s: BN_bin2bn failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 <- pk
        if (!EC_POINT_oct2point(ecGrp, ptPk, &pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnCtx))
        {
            LogPrintf("%s: EC_POINT_oct2point failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT1 = e_i=s_i*G+c_i*P_i
        if (!EC_POINT_mul(ecGrp, ptT1, bnS, ptPk, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        if (!(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptT1 failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 =E_i=s_i*H(P_i)+c_i*I_j

        // ptT2 =H(P_i)
        if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT2) != 0)
        {
            LogPrintf("%s: hashToEC failed.\n", __func__);
            rv = 1; goto End;
        };

        // DEBUGGING: ------- check if we can find the signer...
        // ptSi = Pi * bnT
        if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx)
           || false)
        && (rv = errorN(1, "%s: EC_POINT_mul failed.", __func__)))
            goto End;

        if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) )
            LogPrintf("signer is index %d\n", i);
        // DEBUGGING: - End - check if we can find the signer...

        // ptT3 = s_i*ptT2
        if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT1 = c_i*I_j
        if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = ptT3 + ptT1
        if (!EC_POINT_add(ecGrp, ptT2, ptT3, ptT1, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        if (!(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptT2 failed.\n", __func__);
            rv = 1; goto End;
        };

        CHashWriter ssCHash(SER_GETHASH, PROTOCOL_VERSION);
        ssCHash.write((const char*)tmpPkHash.begin(), 32);
        ssCHash.write((const char*)&tempData[0], 66);
        tmpHash = ssCHash.GetHash();

        if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC))
            || !BN_mod(bnC, bnC, bnOrder, bnCtx))
        {
            LogPrintf("%s: tmpHash -> bnC failed.\n", __func__);
            rv = 1; goto End;
        };
    };

    // bnT = (bnC - bnC1) % N
    if (!BN_mod_sub(bnT, bnC, bnC1, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    // test bnT == 0  (bnC == bnC1)
    if (!BN_is_zero(bnT))
    {
        LogPrintf("%s: signature does not verify.\n", __func__);
        rv = 2;
    };

    End:

    BN_CTX_end(bnCtx);

    EC_POINT_free(ptKi);
    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptSi);

    return rv;
};
Exemplo n.º 18
0
int main(int argc, char** argv)
{
    if (argc != 5)
    {
        std::cerr << "Usage: pp_prove DOCUMENT CHUNKS BLOCK_HASH REVEAL"
            << std::endl;
        return -1;
    }
    const fs::path doc_path = argv[1];
    const std::string chunks_str = argv[2];
    const std::string reveal_str = argv[4];
    size_t chunks = 0, reveal = 0;
    try
    {
        chunks = boost::lexical_cast<size_t>(chunks_str);
        reveal = boost::lexical_cast<size_t>(reveal_str);
    }
    catch (const boost::bad_lexical_cast&)
    {
        std::cerr << "pp_start: bad CHUNKS or REVEAL provided." << std::endl;
        return -1;
    }
    const data_chunk hash = decode_hex(argv[3]);
    if (hash.empty() || hash.size() != hash_size)
    {
        std::cerr << "pp_prove: not a valid BLOCK_HASH." << std::endl;
        return -1;
    }
    std::ifstream infile(doc_path.native(), std::ifstream::binary);
    infile.seekg(0, std::ifstream::end);
    size_t file_size = infile.tellg();
    infile.seekg(0, std::ifstream::beg);
    size_t chunk_size = file_size / chunks;
    // AES works on blocks of 16 bytes. Round up to nearest multiple.
    chunk_size += 16 - (chunk_size % 16);
    BITCOIN_ASSERT(chunk_size % 16 == 0);
    //std::cout << "Creating chunks of "
    //    << chunk_size << " bytes each." << std::endl;
    ec_point_list all_pubkeys;
    while (infile)
    {
        data_chunk buffer(chunk_size);
        // Copy chunk to public chunk file.
        char* data = reinterpret_cast<char*>(buffer.data());
        infile.read(data, chunk_size);
        // Create a seed.
        BITCOIN_ASSERT(ec_secret_size == hash_size);
        ec_secret secret = bitcoin_hash(buffer);
        ec_point pubkey = secret_to_public_key(secret);
        // Once we spend funds, we reveal the decryption pubkey.
        all_pubkeys.push_back(pubkey);
    }
    // Beginning bytes of block hash are zero, so use end bytes.
    std::seed_seq seq(hash.rbegin(), hash.rend());
    index_list random_values(reveal);
    seq.generate(random_values.begin(), random_values.end());
    for (size_t value: random_values)
    {
        size_t index = value % all_pubkeys.size();
        std::cout << (index + 1) << " " << all_pubkeys[index] << std::endl;
    }
    return 0;
}