8 years, 10 months ago.

How do I copy the contents of a byte array to a string while keeping the hex format?

How do I copy a byte array to a string while keeping the hex format? For my example, I would like to copy the content of the 'byte array combined' to the 'spring outputCombined' while keeping the hex format.

#include "mbed.h"

#include <string>

#include "cyassl/ctaocrypt/hmac.h"
#include "cyassl/ctaocrypt/aes.h"

#include "MbedJSONValue.h"
#include "LinearTempSensor.h"

using namespace std;

Serial pc(USBTX, USBRX);

LinearTempSensor sensor(p20, 300, LinearTempSensor::MCP9701);
MbedJSONValue sensorResults;

Aes enc;
Aes dec;

Hmac hmac;

float Vout, Tav, To, TempValue;

std::string s;
std::string JSONoutput;

int main()
{

    pc.baud(115200);

    const byte key[16] = { 0x6d, 0x6e, 0x62, 0x76, 0x63, 0x78, 0x7a, 0x6c, 0x6b, 0x6a, 0x68, 0x67, 0x66, 0x64, 0x73, 0x61 };
    const byte iv[16]  = { 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x70, 0x6f, 0x69, 0x75, 0x79, 0x74, 0x72 };

    byte plain[128];   // an increment of 16, fill with data
    byte cipher[128];
    byte deciphered[128];

    byte hkey[24] = { 0x8b, 0x21, 0x31, 0x21, 0xb7, 0xbe, 0x33, 0x1a, 0xcf, 0x1f, 0x71, 0x70, 0x45, 0xaf, 0x5c, 0x02, 0xa7, 0xa1, 0x4c, 0x34, 0xd4, 0xbc, 0x4b, 0x4a };    // fill key with keying material
    byte buffer[2048];   // fill buffer with data to digest
    byte hmacDigest[SHA256_DIGEST_SIZE];

    Vout = sensor.Sense();          // Sample data (read sensor)
    Tav  = sensor.GetAverageTemp(); // Calculate average temperature from N samples
    To   = sensor.GetLatestTemp();  // Calculate temperature from the latest sample

    TempValue = sensor.GetAverageTemp();

    //Create JSON
    sensorResults["DATA1"][0] = "Result";
    sensorResults["DATA1"][1] = 5.5;
    sensorResults["DATA2"][0] = "Result";
    sensorResults["DATA2"][1] = 700;
    sensorResults["DATA3"][0] = "Result";
    sensorResults["DATA3"][1] = TempValue;

    //Serialize JSON
    s = sensorResults.serialize();
    //sl = s.size();

    //Print JSON string
    pc.printf("json: %s\r\n", s.c_str());

    //Convert JSON string to a char array to encrypt
    //char *a=new char[s.size()+1];
    plain[s.size()]=0;
    memcpy(plain,s.c_str(),s.size());//<-- Fills plain array with the JSON values

    // encrypt
    AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION);
    AesCbcEncrypt(&enc, cipher, plain, sizeof(plain));

    HmacSetKey(&hmac, SHA256, hkey, sizeof(key));
    HmacUpdate(&hmac, buffer, sizeof(buffer));
    HmacFinal(&hmac, hmacDigest);

    //cipher now contains the cipher text from the plain text.

    pc.printf("\r\nAES Key: ");
    for(int i=0; i<sizeof(key); i++) {
        //if(i%16==0) pc.printf("\r\n");
        pc.printf("%.2X",key[i]);
    }

    pc.printf("\r\nAES IV: ");
    for(int i=0; i<sizeof(iv); i++) {
        //if(i%16==0) pc.printf("\r\n");
        pc.printf("%.2X",iv[i]);
    }

    pc.printf("\r\nPlain HEX: ");
    for(int i=0; i<sizeof(plain); i++) {
        //if(i%16==0) pc.printf("\r\n");
        pc.printf("%.2X",plain[i]);
    }

    pc.printf("\r\nEncrypted: ");
    for(int i=0; i<sizeof(cipher); i++) {
        //if(i%16==0) pc.printf("\r\n");
        pc.printf("%.2X",cipher[i]);
    }

    pc.printf("\r\nhmacDigest: ");
    for(int i=0; i<sizeof(hmacDigest); i++) {
        //if(i%16==0) pc.printf("\r\n");
        pc.printf("%.2X",hmacDigest[i]);
    }

    // decrypt
    AesSetKey(&dec, key, sizeof(key), iv, AES_DECRYPTION);
    AesCbcDecrypt(&dec, deciphered, cipher, sizeof(cipher));

    pc.printf("\r\nDecrypted: ");
    for(int  i=0; i<sizeof(deciphered); i++) {
        //if(i%16==0) pc.printf("\r\n");
        //pc.printf("%.2X",deciphered[i]);
        pc.printf("%c",deciphered[i]);
    }

    //Combine the EncryptedData + IV + HMAC
    const int S_CIPHER = sizeof(cipher);
    const int S_IV = sizeof(iv);
    const int S_HMACDIGEST = sizeof(hmacDigest);

    const int S_TOTAL = S_CIPHER + S_IV + S_HMACDIGEST;

    byte combined[S_TOTAL];
    string outputCombined;
    
    //Copy arrays in individually.
    memcpy(combined, cipher, S_CIPHER);
    memcpy(combined + S_CIPHER, iv, S_IV);
    memcpy(combined + S_CIPHER + S_IV, hmacDigest, S_HMACDIGEST);
            
    pc.printf("\r\nOutput: ");
    for(int i=0; i<sizeof(combined); i++) {
        pc.printf("%.2X",combined[i]);
    }
}

2 Answers

8 years, 10 months ago.

Hi Richard,

You can convert byte type to char using (char) function. Eg: byte x; char b=(char)x; and then u can form strings using str[i]=b; where str is a string and b is the 'i'th element of str.

8 years, 10 months ago.

If I understand correctly you have a byte array containing non-ascii values e.g. {0xf0, 0x20, 0xa5} and you want to convert this into a c++ std::string of the hex values e.g. "f020a5"

I think the easiest way would be sprintf to create a char[] in ascii and then convert that to a std::string if needed. Much the same as you are outputting to the PC now but to an internal array rather than the serial port.

If speed or memory were critical then you could do your own hex decoding of each 4bits into an ascii character, since you have a very defined input it should be possible to come up with something smaller and faster than printf but this situation that seems like a pointless complexity.

std::string binToString(byte *inputData, int dataLength) {
  char asciiString[dataLength*2 +1];   // 2 characters per byte plus a null at the end.

  for (int i = 0; i<dataLength; i++) {
    sprintf(asciiString+2*i,"%02X",*(inputData+i));
  }

  asciiString[dataLength*2] = 0; // in theory redundant, the last sprintf should have done this but just to be sure...
  return std::string(asciiString);
}

...

outputCombined = binToString(combined,sizeof(combined));