XOR encryption with a PyObject

Question:

I’m having trouble encrypting bytes from a PyObject using XOR.
For now I only managed to print the bytes as an encoded string (with PyUnicode_AsEncodedString):

Here’s what I tried (taken from this SO answer)

PyObject* repr = PyObject_Repr(wf.str); // wf.str is a PyObject *
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);

printf("REPR: %sn", bytes);

Py_XDECREF(repr);
Py_XDECREF(str);

From here on, I don’t know what to do anymore.
I also tried to access bytes only using PyBytes_AS_STRING(wf.str) and then proceed with the encryption, but it only returned one byte.

There is a way to XOR encrypt bytes taken from a PyObject? Something like this:

bytes = getBytesFromPyObject(wf.str)
encrypted = XOREncryption(bytes)
AssignBytesToPyObject(encrypted, wf.str)

Note: I don’t know much about C, all of this is almost new to me.

Edit: I’m using C instead of Python because I need to implement a function that uses XOR encryption in a built-in module for Python3.

Asked By: Clown Down

||

Answers:

"I also tried to access bytes only using PyBytes_AS_STRING(wf.str)
and then proceed with the encryption, but it only returned one byte."

Are you sure about this? It looks like it is returning a byte pointer byte*.

In C, a pointer to an array is a pointer to the location of the first element in the array. If you add an offset equal to the size of the data you are accessing (in this case, 1 byte), then you should be able to access the following element.

The issue is likely that you need some method to determine the size of your byte array, then you can operate on the byte* that you’ve already accessed and iterate through each byte.

Answered By: h0r53

I know that @h0r53 has already answered my question, but I want to post the code anyway in case it comes useful to someone.

This was implemented in a function (PyMarshal_WriteObjectToString, used for marshal.dump and marshal.dumps) of my custom version of Python, in the marshal.c file

char *bytes = PyBytes_AS_STRING(wf.str);
const char key[32] = {162, 10, 190, 161, 209, 110, 69, 181,
    119, 63, 176, 125, 158, 134, 48, 185,
    200, 22, 41, 43, 212, 144, 131, 169,
    158, 182, 8, 220, 200, 232, 231, 126
};

Py_ssize_t n = PyBytes_Size(wf.str);
for (int i = 0; i < n; i++) {
    bytes[i] = bytes[i] ^ key[i % (sizeof(key) / sizeof(key[0]))];
}

wf.str = PyBytes_FromStringAndSize(bytes, n);
Answered By: Clown Down
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.