ESP8266 WebServer how to stream unsigned char - c++

I was playing around with xxd -i this weekend to convert binary files into unsigned char arrays, thinking I could use it to embed small binary files into arduino code for transmission on mini web and other services. Problem is, it seems the functions in the existing libraries either expect const char *, string or File data types. (and of course, unsigned char arrays aren't really char arrays so they don't convert well to strings)
Not being someone familiar with c++ in depth (still learning) I'm wondering if there is any easy way to stream the unsigned char array created from xxd over the ESP webserver code or something similar? And/or is there a better way to encode a binary file for sending from same?
I'm basically looking at building primarily 'rest' based esp devices, but wanted to have some kind of very rudimentary html/js interface to directly connect and configure basic functionality or get basic telemetry back from the devices. My thought was that with very streamline html/js coding combined with a minify followed by a gzip, I could put such basic primitive interfaces directly into the code in a binary array to be served up when needed. For more complex devices, I've gotten the sd card webserver to work fine, but would prefer not to have to use sd cards for all applications. Before I go back to relying upon html content in huge strings or function calls full of concatenations/prints, I'd like to try to get this to work as another option.
Any help is appreciated.
--- EDITED ---
Example from xxd -i
unsigned char index_htm_gz[] = {
0x1f, 0x8b, 0x08, 0x08, 0x25, 0x38, 0xcf, 0x58, 0x02, 0x03, 0x69, 0x6e,
0x64, 0x65, 0x78, 0x2e, 0x6d, 0x69, 0x6e, 0x2e, 0x68, 0x74, 0x6d, 0x00,
0x5d, 0x8d, 0xb1, 0x6a, 0xc4, 0x30, 0x10, 0x44, 0x7b, 0x7d, 0xc5, 0xe6,
0x03, 0xce, 0x4a, 0xc0, 0x98, 0x14, 0x2b, 0x35, 0x97, 0x40, 0xba, 0x4b,
0x61, 0x08, 0x29, 0x65, 0x7b, 0x2d, 0x2d, 0xb7, 0xb2, 0x8d, 0xb4, 0xc9,
0x91, 0xbf, 0x8f, 0x42, 0xba, 0x83, 0x61, 0x18, 0x1e, 0x33, 0x0c, 0x3e,
0xbc, 0x5c, 0xce, 0xe3, 0xe7, 0xfb, 0x2b, 0x24, 0xcd, 0xe2, 0xf1, 0xcf,
0x41, 0xc2, 0x16, 0x1d, 0x6d, 0x1e, 0x33, 0x69, 0x80, 0x39, 0x85, 0x52,
0x49, 0xdd, 0x97, 0xae, 0xa7, 0x67, 0x8f, 0xca, 0x2a, 0xe4, 0xdf, 0x48,
0x64, 0x07, 0xf3, 0xb1, 0x17, 0x59, 0xd0, 0xfe, 0x33, 0x14, 0xde, 0xae,
0x90, 0x0a, 0xad, 0x6e, 0xae, 0xd5, 0xe6, 0xc0, 0x5b, 0xd7, 0x02, 0x14,
0x12, 0x57, 0xf5, 0x47, 0xa8, 0x26, 0x22, 0x6d, 0x1f, 0x4f, 0x77, 0xf3,
0x06, 0xf0, 0xf0, 0x63, 0xe2, 0x0a, 0x4d, 0x01, 0x6e, 0x34, 0xc1, 0x11,
0x22, 0x75, 0x68, 0x0f, 0x8f, 0x9c, 0x23, 0x4c, 0x7b, 0x59, 0xa8, 0xb8,
0x47, 0x48, 0xc4, 0x31, 0xa9, 0x1b, 0x7a, 0x30, 0xb5, 0xcc, 0x8e, 0x73,
0xab, 0x55, 0xfb, 0x3d, 0x45, 0xda, 0x87, 0xbe, 0x8b, 0xbc, 0xc2, 0x8d,
0x17, 0x4d, 0xad, 0xe0, 0x8d, 0xf9, 0x05, 0x3d, 0x2a, 0xb3, 0xe0, 0xdd,
0x00, 0x00, 0x00
};
unsigned int index_htm_gz_len = 207;
As mentioned in comments, one thing I tried was switching the type from unsigned char to const char then running through the following:
void sendCompressed(String content_type, const char * content, unsigned int len) {
webServer.setContentLength(len);
webServer.sendHeader("Content-Encoding", "gzip");
webServer.send(200, content_type, String(content));
}
In such a case, my handleRoot function would call the sendCompressed with the data from the header:
void function handleRoot() {
sendCompressed("text/html", index_htm_gz, index_htm_gz_len);
}
It compiled without errors, but outputs nothing. I would also expect this not to be ideal as String data is generally 7-bit and obviously, binary compressed data is not.

This binary serve worked for me:
const char favicon[1344] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
... // ( way shortened )
0x44, 0xae, 0x42, 0x60, 0x82
};
void handleFavicon() {
server.send_P(200, "image/x-icon", favicon, sizeof(favicon));
}
server.on("/favicon.ico", handleFavicon); // in setup() or something like it
you might need to adjust your gzip header, but this method of embeding binary content works enough to show the right icon, i'd imaging a gzip stream works the same way...

Related

C++ negative byte value

I have c++ code that read 16 byte from a file as char value
And I have a table of unsigned char from 0 to 255
I want to use byte values from file as a index in my unsigned char table to change the original file byte values but I get negative value from file and as you know you can't use negative value as a index in array
What should I do ?
Edit
const unsigned char TopSbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
void RunFunction(){
ifstream reader;
ofstream writer;
reader.open(myfile_address, ifstream::binary);
writer.open(storage_file,ofstream::out);
unsigned int BufferSize =16;
char *Transform_Buffer = new char[BufferSize];
reader.read(Transform_Buffer, BufferSize);
ExchangeData(Transform_Buffer, BufferSize);
writer.write(Transform_Buffer, BufferSize);
writer.flush();
}
void EData::ExchangeData(char data[], const unsigned int size){
for (unsigned int i = 0; i<size; i++){
data[i] = TopSbox[data[i]];
}
}
Don't use operator new unless absolutely necessary.
Rather than
char *Transform_Buffer = new char[BufferSize];
you can define the buffer as a local array:
const unsigned int BufferSize = 16;
unsigned char Transform_Buffer[BufferSize];
For this to work, you should declare BufferSize as const. Notice also that I declared the elements of the buffer as unsigned char.
Then, this line
reader.read(Transform_Buffer, BufferSize);
can be replaced with
reader.read(reinterpret_cast<char*>(Transform_Buffer), BufferSize);
and similarly for writer.
Please also replace all char* in function declarations with unsigned char*, eg:
void EData::ExchangeData(unsigned char data[], const unsigned int size){
I guess everything should work as expected now.
Just have buffer of unsigned chars. Then pass it as char* to ifstream::read. Let's say char* works kind of like a generic pointer.
You may want to prefer to use standard containers.
std::vector<unsigned char> transform_buffer(buffer_size);
reader.read(static_cast<char*>(transform_buffer.data()), transform_buffer.size());
exchange_data(transform_buffer);
}
void exchange_data(std::vector<unsigned char>& transform_buffer) {
for (auto&& i : transform_buffer) {
i = TopSbox[i];
}
}

How to decode MAP Invoke messages using asn1c generated code

I am using the c code generated by asn1c from the MAP protocol specification (i.e., the corresponding ASN1 files). Please consider the following sample code:
// A real byte stream of a MAP message:
unsigned char packet_bytes[] = {
0xa2, 0x60, 0x02, 0x01, 0x00, 0x30, 0x5b, 0x02,
0x01, 0x38, 0xa3, 0x56, 0xa1, 0x54, 0x30, 0x52,
0x04, 0x10, 0x7a, 0x0e, 0x1f, 0xef, 0x73, 0x77,
0xbe, 0xb0, 0x9d, 0x6f, 0x23, 0x13, 0xfb, 0xc2,
0x32, 0xa6, 0x04, 0x08, 0x65, 0xda, 0x19, 0x1e,
0x18, 0x4b, 0x04, 0x99, 0x04, 0x10, 0x47, 0xe1,
0x36, 0x82, 0xe9, 0xb3, 0xf3, 0x54, 0x76, 0x67,
0x1d, 0xe4, 0xed, 0x25, 0xc8, 0x76, 0x04, 0x10,
0x37, 0x1d, 0x80, 0x82, 0xde, 0xec, 0x70, 0x51,
0xc6, 0xcd, 0x08, 0xc9, 0x30, 0x64, 0xc6, 0x54,
0x04, 0x10, 0x82, 0xbc, 0x2d, 0xdb, 0x1d, 0x92,
0x82, 0x34, 0x55, 0xbc, 0xeb, 0x87, 0x72, 0xf3,
0x90, 0xce
};
// Initializing ...
MAP_Component_t _pdu, *pdu = &_pdu;
memset(pdu, 0, sizeof(*pdu));
// Decoding:
asn_dec_rval_t dec_ret = ber_decode(NULL, &asn_DEF_MAP_Component, (void **) &pdu, MAP_packet_bytes, sizeof(MAP_packet_bytes));
The invokeId and opCode parameters are truely detected, and the parser gives us a buffer named as invokeParameters which is of type ANY.
GSM Mobile Application
Component: invoke (1)
invoke
invokeID: -70
opCode: localValue (0)
invokeParameters: ....
The question is how to decode (parse) invokeParameters?
GSM Mobile Application
Component: returnResultLast (2)
returnResultLast
invokeID: 0
resultretres
opCode: localValue (0)
localValue: sendAuthenticationInfo (56)
authenticationSetList: quintupletList (1)
quintupletList: 1 item
AuthenticationQuintuplet
rand: 7a0e1fef7377beb09d6f2313fbc232a6
xres: 65da191e184b0499
ck: 47e13682e9b3f35476671de4ed25c876
ik: 371d8082deec7051c6cd08c93064c654
autn: 82bc2ddb1d92823455bceb8772f390ce
The invokeId and opCode parameters are truely detected, and the parser gives us a buffer named as invokeParameters which is of type ANY.
The question is how to decode (parse) invokeParameters?
You need to call ber_decode with the appropriate type (depending on the operation code) and the content of the ANY buffer. From ANY.h
typedef struct ANY {
uint8_t *buf; /* BER-encoded ANY contents */
int size; /* Size of the above buffer */
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
} ANY_t;
In your case it should be something like
SendAuthenticationInfoArg_t _sai, *sai = &_sai;
memset(sai, 0, sizeof(*sai));
asn_dec_rval_t dec_ret = ber_decode(NULL,
&asn_DEF_SendAuthenticationInfoArg,
(void **) &sai,
_pdu.invoke.invokeparameter->buf,
_pdu.invoke.invokeparameter->size);

IntelĀ® TinyCrypt: how to use AES-128/CTR

I need to do AES-128/CTR encryption/decryption using Intel TinyCrypt (written in C). I took a look at the test case provided by the library, but still have a few questions on how to use it. Here's the code of the test case (see the complete source code here):
/*
* NIST SP 800-38a CTR Test for encryption and decryption.
*/
uint32_t test_1_and_2(void)
{
const uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c
};
uint8_t ctr[16] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff
};
const uint8_t plaintext[64] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11,
0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46,
0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b,
0xe6, 0x6c, 0x37, 0x10
};
const uint8_t ciphertext[80] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff, 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, 0xf6, 0x6b,
0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02,
0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1,
0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
};
struct tc_aes_key_sched_struct sched;
uint8_t out[80];
uint8_t decrypted[64];
uint32_t result = TC_PASS;
TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n");
(void)tc_aes128_set_encrypt_key(&sched, key);
(void)memcpy(out, ctr, sizeof(ctr));
if (tc_ctr_mode(&out[TC_AES_BLOCK_SIZE], sizeof(plaintext),
plaintext, sizeof(plaintext), ctr, &sched) == 0) {
TC_ERROR("CTR test #1 (encryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(1, ciphertext, sizeof(out), out, sizeof(out));
TC_END_RESULT(result);
TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n");
(void) memcpy(ctr, out, sizeof(ctr));
if (tc_ctr_mode(decrypted, sizeof(decrypted), &out[TC_AES_BLOCK_SIZE],
sizeof(decrypted), ctr, &sched) == 0) {
TC_ERROR("CTR test #2 (decryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(2, plaintext, sizeof(plaintext),
decrypted, sizeof(plaintext));
exitTest1:
TC_END_RESULT(result);
return result;
}
My input data is a double pointer (2D array) and I'd like to keep it that way:
uint8_t ** mydata = gen_rand_data(const size_t height, const size_t length);
Here's my understanding (correct me if I'm wrong):
AES-128 is a block cipher, with 128-bit key.
CTR mode makes the AES-128 a stream cipher and lets encrypt/decrypt data with arbitrary size.
Having AES-128/CTR, the output (ciphertext) has the same length as plaintext.
To improve the security, it's better to use 128-bit IV (nonce) for encryption.
Now here's my questions:
Can I say ctr (initial counter, right?) is our IV?
Why the ciphertext (expected value) and out (calculated value) are 128-bit bigger than plaintext?
Why the code copies ctr value in the beginning of out?
To encrypt mydata (2D array), I just need to loop over it and simple feed bytes from mydata to tc_ctr_mode, regardless of the dimension of mydata. Is this correct?
Thanks in advance.
The counter is generally supplied as the iv parameter if there is no specific counter parameter.
The output is 16-bytes longer because the counter is prepended, the counter is block sized and AES has a 16-byte block size..
The counter value is not secret and is needed for decryption. Since the same key/counter combination can never be reused if the key is going to be reused (a common situation) the counter must be unique and thus not pre-shared. The general answer is to pre-pend the counter value to the encrypted data.
Yes providing the decryption end knows a priori the array dimensions. But is is probably better to use some form of marshaling to preserve the array shape.

Lookup table does not work as expected

I have a weird issue while creating a substitution for AES encryption.
I use a lookup table, named SBox, to substitute the bytes in the string state (technically a vector, but it's irrelevant)
const vector<byte> SBox =
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
void subBytes(vector<string>& state)
{
for (int i=0; i<4; ++i)
{
for (int j=0; j<4; ++j)
{
state[i][j] = SBox[state[i][j]];
}
}
}
this does not work but if I use
state[i][j] = SBox[state[i][j]&0xff];
then everything magically works again. I thought a char was byte-sized, so AND'ing by 0xff had no influence. FYI I am running under 64-bit machine. This is a little bit annoying as I have to use a lot of lines like that in other functions. Can anybody explain why? Is there another solution?
state[i][j] may return signed chars so if your character codes are larger than 7bits you are using negative index to SBox[state[i][j]]
Another thing:
if you have fix sizes for SBox and states: why not using std::array instead of vector?
std::array<byte,256> for SBox
and std::array<std::array<char,4>,4> for State.
Also you may use the size member of your vectors or arrays instead using magic number in your loop.

How can I represent an array of bytes in Python?

I have to translale some code into python. Both are to be 32 bits. How do I verify that?
const char kEncryptionKey[] = {
0xb0, 0x8c, 0x70, 0xcf, 0xbc, 0xb0, 0xeb, 0x6c, 0xab, 0x7e, 0x82, 0xc6,
0xb7, 0x5d, 0xa5, 0x20, 0x72, 0xae, 0x62, 0xb2, 0xbf, 0x4b, 0x99, 0x0b,
0xb8, 0x0a, 0x48, 0xd8, 0x14, 0x1e, 0xec, 0x07
};
const char kIntegrityKey[] = {
0xbf, 0x77, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1, 0xd8, 0xcd, 0x18, 0x62,
0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0, 0xc4, 0xce, 0x8a,
0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92
};
So..in python:
kIntegrityKey = ????
kEncryptionKey = ????
You could store your hexadecimal numbers in a list:
kIntegrityKey = [0xbf, 0x77, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1, 0xd8, 0xcd, 0x18, 0x62,
0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0, 0xc4, 0xce, 0x8a,
0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92]
and the same thing to kEncryptionKey.
Update: If you have concerns related to the size of your data, you could pack your data into an array. For example:
>>> import array
>>> kIntegrityKey = array.array('B', [0xbf, 0x77, 0xec, 0x55, 0xc3, 0x01, 0x30, 0xc1,
... 0xd8, 0xcd, 0x18, 0x62, 0xed, 0x2a, 0x4c, 0xd2, 0xc7, 0x6a, 0xc3, 0x3b, 0xc0, 0xc4,
... 0xce, 0x8a, 0x3d, 0x3b, 0xbd, 0x3a, 0xd5, 0x68, 0x77, 0x92])
>>> len(kIntegrityKey)
32
>>> kIntegrityKey.itemsize
1
The first argument to array ('B') indicates that we want to store the second parameter (your unsigned char list) using a list of unisgned char.
The itemsize attribute is described in the docstring as:
itemsize -- the length in bytes of one array item
Python strings can be given arbitrary hex characters using the \x special character.
kIntegrityKey = "\xb0\x8c\x70\xcf ..."
Py3k has a "bytes" type which is likely ideal for this application.
NB: python 2 has a bytes type now too, but it's just an alias of str.