Alison Y.

asked • 09/26/23

I have a C++ problem, i am dealing with a server client AES encyrption assignment and I have been tasked with filling in this function stub?

Function stub: // Send a message to the server,

using the common format for secure messages,

// then take the response from

the server, decrypt it, and return

it・

///

/// Many of the messages in our server have a common form (@rblock. @ablock):

///

- erblock enc (pubkey,

padR ("CD" aeskey. length ( (msg)))

// - @ablock enc(aeskey, (msg)

///

/ @param sd An open socket /// @param pub The server's public key, for encrypting the aes key /// @param cmd The command that is being sent

// @param msg The contents of the

@ablock

///

/// @returns a vector with the (decrypted) result, or an empty vector on error vector<uint8

t> send_cmd(int sd,

RSA *pub, const string cmd, const vector<uint8

_t> &msg) {

}

Helper functions:

/// Run the AES symmetric encryption/decryption algorithm on a buffer of bytes.

/// Note that this will do either encryption or decryption, depending on how the

/// provided CTX has been configured. After calling, the CTX cannot be used

/// again until it is reset.

///

/// NB: This is a forward declaration. This version of aes_crypt_msg is

/// implemented in my_crypto.cc.

///

/// @param ctx The pre-configured AES context to use for this operation

/// @param msg A buffer of bytes to encrypt/decrypt

///

/// @return A vector with the encrypted or decrypted result, or an empty

/// vector if there was an error

vector<uint8_t> aes_crypt_msg(EVP_CIPHER_CTX *ctx, const unsigned char *start,

int count);


/// Run the AES symmetric encryption/decryption algorithm on a vector. Note

/// that this will do either encryption or decryption, depending on how the

/// provided CTX has been configured. After calling, the CTX cannot be used

/// again until it is reset.

///

/// @param ctx The pre-configured AES context to use for this operation

/// @param msg A vector to encrypt/decrypt

///

/// @return A vector with the encrypted or decrypted result, or an empty

/// vector if there was an error

vector<uint8_t> aes_crypt_msg(EVP_CIPHER_CTX *ctx, const vector<uint8_t> &msg) {

return aes_crypt_msg(ctx, msg.data(), msg.size());

}


/// Run the AES symmetric encryption/decryption algorithm on a string. Note that

/// this will do either encryption or decryption, depending on how the provided

/// CTX has been configured. After calling, the CTX cannot be used again until

/// it is reset.

///

/// @param ctx The pre-configured AES context to use for this operation

/// @param msg A string to encrypt/decrypt

///

/// @return A vector with the encrypted or decrypted result, or an empty

/// vector if there was an error

vector<uint8_t> aes_crypt_msg(EVP_CIPHER_CTX *ctx, const string &msg) {

return aes_crypt_msg(ctx, (unsigned char *)msg.c_str(), msg.length());

}


/// Create an AES key. A key is two parts, the key itself, and the

/// initialization vector. Each is just random bits. Our key will be a stream

/// of random bits, long enough to be split into the actual key and the iv.

///

/// @return A vector holding the key and iv bits, or an empty vector on error

vector<uint8_t> create_aes_key() {

vector<uint8_t> key(AES_KEYSIZE + AES_IVSIZE);

if (!RAND_bytes(key.data(), AES_KEYSIZE) ||

!RAND_bytes(key.data() + AES_KEYSIZE, AES_IVSIZE))

return err<vector<uint8_t>>({}, "Error in RAND_bytes()");

return key;

}


/// Create an aes context for doing a single encryption or decryption. The

/// context must be reset after each full encrypt/decrypt.

///

/// @param key A vector holding the bits of the key and iv

/// @param encrypt true to encrypt, false to decrypt

///

/// @return An AES context for doing encryption. Note that the context can be

/// reset in order to re-use this object for another encryption.

EVP_CIPHER_CTX *create_aes_context(const vector<uint8_t> &key, bool encrypt) {

// create and initialize a context for the AES operations we are going to do

EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

if (ctx == nullptr)

return err<EVP_CIPHER_CTX *>(nullptr,

"Error: OpenSSL couldn't create context: ",

ERR_error_string(ERR_get_error(), 0));

ContextManager c([&]() { EVP_CIPHER_CTX_cleanup(ctx); }); // reclaim on exit


// Make sure the key and iv lengths we have up above are valid

if (!EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), 0, 0, 0, encrypt))

return err<EVP_CIPHER_CTX *>(nullptr,

"Error: OpenSSL couldn't initialize context: ",

ERR_error_string(ERR_get_error(), 0));

if ((EVP_CIPHER_CTX_key_length(ctx) != AES_KEYSIZE) ||

(EVP_CIPHER_CTX_iv_length(ctx) != AES_IVSIZE))

return err<EVP_CIPHER_CTX *>(nullptr,

"Error: OpenSSL couldn't initialize context: ",

ERR_error_string(ERR_get_error(), 0));


// Set the key and iv on the AES context, and set the mode to encrypt or

// decrypt

if (!EVP_CipherInit_ex(ctx, nullptr, nullptr, key.data(),

key.data() + AES_KEYSIZE, encrypt))

return err<EVP_CIPHER_CTX *>(nullptr,

"Error: OpenSSL couldn't re-init context: ",

ERR_error_string(ERR_get_error(), 0));

c.disable(); // don't reclaim ctx on exit, because we're good

return ctx;

}


1 Expert Answer

By:

Jose R. answered • 07/16/24

Tutor
New to Wyzant

Still looking for help? Get the right answer, fast.

Ask a question for free

Get a free answer to a quick problem.
Most questions answered within 4 hours.

OR

Find an Online Tutor Now

Choose an expert and meet online. No packages or subscriptions, pay only for the time you need.