bool tx_extra_message::decrypt(size_t index, const Crypto::PublicKey &txkey, const Crypto::SecretKey *recepient_secret_key, std::string &message) const { size_t mlen = data.size(); if (mlen < TX_EXTRA_MESSAGE_CHECKSUM_SIZE) { return false; } const char *buf; std::unique_ptr<char[]> ptr; if (recepient_secret_key != nullptr) { ptr.reset(new char[mlen]); assert(ptr); message_key_data key_data; if (!generate_key_derivation(txkey, *recepient_secret_key, key_data.derivation)) { return false; } key_data.magic1 = 0x80; key_data.magic2 = 0; Hash h = cn_fast_hash(&key_data, sizeof(message_key_data)); uint64_t nonce = SWAP64LE(index); chacha(10, data.data(), mlen, reinterpret_cast<uint8_t *>(&h), reinterpret_cast<uint8_t *>(&nonce), ptr.get()); buf = ptr.get(); } else { buf = data.data(); } mlen -= TX_EXTRA_MESSAGE_CHECKSUM_SIZE; for (size_t i = 0; i < TX_EXTRA_MESSAGE_CHECKSUM_SIZE; i++) { if (buf[mlen + i] != 0) { return false; } } message.assign(buf, mlen); return true; }
void ChaCha::set_iv(const byte iv[], size_t length) { if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); m_state[12] = 0; m_state[13] = 0; if(length == 8) { m_state[14] = load_le<u32bit>(iv, 0); m_state[15] = load_le<u32bit>(iv, 1); } else if(length == 12) { m_state[13] = load_le<u32bit>(iv, 0); m_state[14] = load_le<u32bit>(iv, 1); m_state[15] = load_le<u32bit>(iv, 2); } chacha(m_buffer.data(), m_state.data()); ++m_state[12]; m_state[13] += (m_state[12] == 0); m_position = 0; }
/* * Combine cipher stream with message */ void ChaCha::cipher(const byte in[], byte out[], size_t length) { while(length >= m_buffer.size() - m_position) { xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position); length -= (m_buffer.size() - m_position); in += (m_buffer.size() - m_position); out += (m_buffer.size() - m_position); chacha(m_buffer.data(), m_state.data()); ++m_state[12]; m_state[13] += (m_state[12] == 0); m_position = 0; } xor_buf(out, in, &m_buffer[m_position], length); m_position += length; }
bool tx_extra_message::encrypt(size_t index, const std::string &message, const AccountPublicAddress *recipient, const KeyPair &txkey) { size_t mlen = message.size(); std::unique_ptr<char[]> buf(new char[mlen + TX_EXTRA_MESSAGE_CHECKSUM_SIZE]); memcpy(buf.get(), message.data(), mlen); memset(buf.get() + mlen, 0, TX_EXTRA_MESSAGE_CHECKSUM_SIZE); mlen += TX_EXTRA_MESSAGE_CHECKSUM_SIZE; if (recipient) { message_key_data key_data; if (!generate_key_derivation(recipient->spendPublicKey, txkey.secretKey, key_data.derivation)) { return false; } key_data.magic1 = 0x80; key_data.magic2 = 0; Hash h = cn_fast_hash(&key_data, sizeof(message_key_data)); uint64_t nonce = SWAP64LE(index); chacha(10, buf.get(), mlen, reinterpret_cast<uint8_t *>(&h), reinterpret_cast<uint8_t *>(&nonce), buf.get()); } data.assign(buf.get(), mlen); return true; }