src/utils/cryptmsg.cpp
size_t encryptMsg(size_t inputSize, const uint8_t* input, size_t BkeysCount, const crypto::public_key* Bkeys, size_t outputSize, uint8_t* output)
{
    if(!inputSize || !BkeysCount)
        return 0;

    //prepare
    size_t msgHeadSize = sizeof(CryptoMessageHead) + (BkeysCount - 1) * sizeof(XEntry);
    size_t msgSize = msgHeadSize + getEncryptChachaSize(inputSize);
    if(outputSize < msgSize)
        return msgSize;
    if(!input || !Bkeys || !output)
        return 0;

    //make decorated session key
    SessionX X; X.cstart = cStart; X.cend = cEnd;
    //generate session key X.x
    {
        crypto::public_key tmpX;
        crypto::generate_keys(tmpX,X.x);
    }
    //chacha encrypt input with x
    encryptChacha(input, inputSize, X.x, output + msgHeadSize);

    //fill head
    CryptoMessageHead& head = *reinterpret_cast<CryptoMessageHead*>(output);
    head.plainSize = native_to_little(uint32_t(inputSize));
    crypto::secret_key r;
    crypto::generate_keys(head.R, r);
    head.count = native_to_little(uint16_t(BkeysCount));
    //fill XEntry for each B
    const crypto::public_key* pB = Bkeys;
    XEntry* pxe = head.xentries;
    for(size_t i=0; i<BkeysCount; ++i, ++pxe, ++pB)
    {
        const crypto::public_key& B = *pB;
        XEntry& xe = *pxe;
        xe.Bhash = getBhash(B);
        //get rB key
        crypto::key_derivation rBv;
        crypto::generate_key_derivation(B, r, rBv);
        crypto::secret_key rB;
        crypto::derivation_to_scalar(rBv, 0, rB);
        //encrypt X with rB key
        encryptChacha(reinterpret_cast<const uint8_t*>(&X), sizeof(X), rB, xe.cipherX);
    }
    return msgSize;
}
/*!
 * \brief encryptMsg - encrypts data for recipients using their B public keys (assumed public view keys).
 *
 * The result has following structure [plainSize:32][R:32][count of XEntrys:16][XEntry]...[XEntry][x encrypted data:+8*8]
 * plainSize - size of original data, x encrypted data takes 8 more bytes
 * [XEntry] - [Bhash:32][rBX] pair for each recipient
 * where Bhash - xor of B (aka fingerprint of B, using which recipient can find his entry)
 * [rBX:+8*8] - encrypted X (aka SessionX)
 * [X] = [cstart:8][x:32*8][cend:8]
 *
 * \param inputSize - input buffer size.
 * \param input - input buffer to encrypt.
 * \param BkeysCount - count of B keys.
 * \param Bkeys - array of B keys for each recipients.
 * \param outputSize - output buffer size.
 * \param output - output buffer.
 * \returns output size required if output==nullptr or outputSize is not enough.
 * returns 0 on error
 */
\brief encryptMsg - encrypts data for recipients using their B public keys (assumed public view keys).

\param inputSize - input buffer size.
\param input - input buffer to encrypt.
\param BkeysCount - count of B keys.
\param Bkeys - array of B keys for each recipients.
\param outputSize - output buffer size.
\param output - output buffer.
\returns output size required if output==nullptr or outputSize is not enough.
returns 0 on error
\ brief encryptMsg - encrypts data for recipients using their B public keys ( assumed public view keys ) . \ param inputSize - input buffer size . \ param input - input buffer to encrypt . \ param BkeysCount - count of B keys . \ param Bkeys - array of B keys for each recipients . \ param outputSize - output buffer size . \ param output - output buffer . \ returns output size required if output == nullptr or outputSize is not enough . returns 0 on error
size_t encryptMsg(size_t inputSize, const uint8_t* input, size_t BkeysCount, const crypto::public_key* Bkeys, size_t outputSize, uint8_t* output)
{
    if(!inputSize || !BkeysCount)
        return 0;
    size_t msgHeadSize = sizeof(CryptoMessageHead) + (BkeysCount - 1) * sizeof(XEntry);
    size_t msgSize = msgHeadSize + getEncryptChachaSize(inputSize);
    if(outputSize < msgSize)
        return msgSize;
    if(!input || !Bkeys || !output)
        return 0;
    SessionX X; X.cstart = cStart; X.cend = cEnd;
    {
        crypto::public_key tmpX;
        crypto::generate_keys(tmpX,X.x);
    }
    encryptChacha(input, inputSize, X.x, output + msgHeadSize);
    CryptoMessageHead& head = *reinterpret_cast<CryptoMessageHead*>(output);
    head.plainSize = native_to_little(uint32_t(inputSize));
    crypto::secret_key r;
    crypto::generate_keys(head.R, r);
    head.count = native_to_little(uint16_t(BkeysCount));
    const crypto::public_key* pB = Bkeys;
    XEntry* pxe = head.xentries;
    for(size_t i=0; i<BkeysCount; ++i, ++pxe, ++pB)
    {
        const crypto::public_key& B = *pB;
        XEntry& xe = *pxe;
        xe.Bhash = getBhash(B);
        crypto::key_derivation rBv;
        crypto::generate_key_derivation(B, r, rBv);
        crypto::secret_key rB;
        crypto::derivation_to_scalar(rBv, 0, rB);
        encryptChacha(reinterpret_cast<const uint8_t*>(&X), sizeof(X), rB, xe.cipherX);
    }
    return msgSize;
}
size_t encryptMsg ( size_t inputSize , const uint8_t * input , size_t BkeysCount , const crypto :: public_key * Bkeys , size_t outputSize , uint8_t * output ) { if ( ! inputSize || ! BkeysCount ) return 0 ; size_t msgHeadSize = sizeof ( CryptoMessageHead ) + ( BkeysCount - 1 ) * sizeof ( XEntry ) ; size_t msgSize = msgHeadSize + getEncryptChachaSize ( inputSize ) ; if ( outputSize < msgSize ) return msgSize ; if ( ! input || ! Bkeys || ! output ) return 0 ; SessionX X ; X . cstart = cStart ; X . cend = cEnd ; { crypto :: public_key tmpX ; crypto :: generate_keys ( tmpX , X . x ) ; } encryptChacha ( input , inputSize , X . x , output + msgHeadSize ) ; CryptoMessageHead & head = * reinterpret_cast < CryptoMessageHead * > ( output ) ; head . plainSize = native_to_little ( uint32_t ( inputSize ) ) ; crypto :: secret_key r ; crypto :: generate_keys ( head . R , r ) ; head . count = native_to_little ( uint16_t ( BkeysCount ) ) ; const crypto :: public_key * pB = Bkeys ; XEntry * pxe = head . xentries ; for ( size_t i = 0 ; i < BkeysCount ; ++ i , ++ pxe , ++ pB ) { const crypto :: public_key & B = * pB ; XEntry & xe = * pxe ; xe . Bhash = getBhash ( B ) ; crypto :: key_derivation rBv ; crypto :: generate_key_derivation ( B , r , rBv ) ; crypto :: secret_key rB ; crypto :: derivation_to_scalar ( rBv , 0 , rB ) ; encryptChacha ( reinterpret_cast < const uint8_t * > ( & X ) , sizeof ( X ) , rB , xe . cipherX ) ; } return msgSize ; }
\brief encryptMsg - encrypts data for recipients using their B public keys (assumed public view keys).
\ brief encryptMsg - encrypts data for recipients using their B public keys ( assumed public view keys ) .
//prepare //make decorated session key //generate session key X.x //chacha encrypt input with x //fill head //fill XEntry for each B //get rB key //encrypt X with rB key