5

I have two hexadecimal values which is stored as string:

string md5OfPath("a77e0a3e517e0a9d44c3a823d96ca83c");
string guidValue("c3b491e559ac4f6a81e527e971b903ed");

I want to perform XOR operation on both the values in C++. Can you please suggest me on how I can perform the xor operation.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
sanam_bl
  • 299
  • 1
  • 7
  • 14

6 Answers6

5

I think the straight-forward loop should do the trick:

static inline unsigned int value(char c)
{
    if (c >= '0' && c <= '9') { return c - '0';      }
    if (c >= 'a' && c <= 'f') { return c - 'a' + 10; }
    if (c >= 'A' && c <= 'F') { return c - 'A' + 10; }
    return -1;
}

std::string str_xor(std::string const & s1, std::string const & s2)
{
    assert(s1.length() == s2.length());

    static char const alphabet[] = "0123456789abcdef";

    std::string result;
    result.reserve(s1.length());

    for (std::size_t i = 0; i != s1.length(); ++i)
    { 
        unsigned int v = value(s1[i]) ^ value(s2[i]);

        assert(v < sizeof alphabet);

        result.push_back(alphabet[v]);
    }

    return result;
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Hi,I tried your suggestion, but I am getting some error in the line assert(v < sizeof alphabet); Have I done something wrong. Below is my code – sanam_bl Oct 01 '12 at 11:23
  • 1
    @sanam_bl: You don't need the asserts. They're just for illustration. You can remove those lines. Otherwise `#include `. – Kerrek SB Oct 01 '12 at 11:27
  • when I print out the value of v , during the third iteration value of v is 4294967284 which is greater than alphabet. and that's why the assert is failing – sanam_bl Oct 01 '12 at 11:36
  • Note that there's no guarantee that the code points `'a'` to `'f'` (or `'A'` to `'F'`) are contiguous. The cleanest and simplest way to convert a single character to a digit is table lookup. – James Kanze Oct 01 '12 at 12:23
  • @sanam_bl: Sorry, had a really stupid error in the conversion function! Fixed now. – Kerrek SB Oct 01 '12 at 12:40
2

Iterate through the characters of the strings in parallel and do the XOR operation character-by-character, appending characters to a result string as you go through them.

Oh, the XOR operator is ^.

You can have a map for characters to hexadecimal values:

`0` -> 0x0
`1` -> 0x1
...
`a` -> 0xa

And apply the ^ operator on the values, not the characters themselves.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Is it possible to perform xor on each individual character? for eg : a ^ c ? – sanam_bl Oct 01 '12 at 10:38
  • 2
    @sanam_bl it is, but that probably won't give you the result you expect. Note that the character `'a'` isn't the same as the hexadecimal number `0xa`. You'll have to convert it yourself. – Luchian Grigore Oct 01 '12 at 10:39
0

Split it into shorter strings and follow this answer for converting hex strings to ints for each. Then you can XOR or whatever you like on the array of ints you get back.

Splitting into 4 character strings should work; if you use 8 characters you'll hit the 32-bit signed int problem (i.e. negative numbers).

Community
  • 1
  • 1
Phil H
  • 19,928
  • 7
  • 68
  • 105
0

The functional approach to compining two ranges into one in C++ is to use std::transform. In your case, all you need is a function object which performs the xor operation:

#include <functional>

template <typename T>
struct Xor : std::binary_function<T, T, T> {
    T operator() (T a, T b) {
        return a ^ b;
    }
};

You can use that to construct a function which xors all characters in two strings:

#include <cassert>
#include <functional>
#include <iterator>
#include <string>

static std::string xorStrings( const std::string &s1,
                               const std::string &s2 )
{
    std::assert( s1.size() == s2.size() );

    std::string result;
    result.reserve( s1.size() );

    std::transform( s1.begin(), s1.end(),
                    s2.begin(),
                    std::back_inserter( result ),
                    Xor<std::string::value_type>() );

    return result;
}
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
0

The following function (xorTwoHexStrings(string str1, string str2)) can be used

#include<sstream>

int hexCharToInt(char a){
    if(a>='0' && a<='9')
        return(a-48);
    else if(a>='A' && a<='Z')
        return(a-55);
    else
        return(a-87);
}

string xorTwoHexStrings(string str1, string str2){
    std::stringstream XORString;
    for(int i=0;i<str2.length();i++){
        XORString << hex << (hexCharToInt(str1[i])^hexCharToInt(str2[i]));
    }
    return XORString.str();
}
0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

const char* quads[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };

const char * chrTObin(unsigned char c) {
  if(c >= '0' && c <= '9') return quads[     c - '0'];
  if(c >= 'A' && c <= 'F') return quads[10 + c - 'A'];
  if(c >= 'a' && c <= 'f') return quads[10 + c - 'a'];
  return NULL;
  //return -1;
}

char* xorHash(char* chrXOR1, char* chrXOR2) {

    int x;
    int xPos;

    int intXOR1 = strlen(chrXOR1);


    char strBin1[4];
    char strBin2[4];
    char strBin[8];
    char strXORED[4];
    char newXOR[128];

    strcpy(newXOR, "");

    for(x = 0; x < intXOR1; x++) {

        strcpy(strBin, "");
        strcat(strBin, chrTObin(chrXOR1[x]));
        strcat(strBin, chrTObin(chrXOR2[x]));

        strcpy(strXORED, "");

        if(strlen(strBin) == 8) {
            for(xPos = 0; xPos < 4; xPos++) {
                if(strBin[xPos] == strBin[xPos+4]) {
                    strcat(strXORED, "0");
                } else {
                    strcat(strXORED, "1");
                }
            }
        }

        if(strcmp(strXORED, "0000") == 0) {
            strcat(newXOR, "0");
        } else if(strcmp(strXORED, "0001") == 0) {
            strcat(newXOR, "1");
        } else if(strcmp(strXORED, "0010") == 0) {
            strcat(newXOR, "2");
        } else if(strcmp(strXORED, "0011") == 0) {
            strcat(newXOR, "3");
        } else if(strcmp(strXORED, "0100") == 0) {
            strcat(newXOR, "4");
        } else if(strcmp(strXORED, "0101") == 0) {
            strcat(newXOR, "5");
        } else if(strcmp(strXORED, "0110") == 0) {
            strcat(newXOR, "6");
        } else if(strcmp(strXORED, "0111") == 0) {
            strcat(newXOR, "7");
        } else if(strcmp(strXORED, "1000") == 0) {
            strcat(newXOR, "8");
        } else if(strcmp(strXORED, "1001") == 0) {
            strcat(newXOR, "9");
        } else if(strcmp(strXORED, "1010") == 0) {
            strcat(newXOR, "A");
        } else if(strcmp(strXORED, "1011") == 0) {
            strcat(newXOR, "B");
        } else if(strcmp(strXORED, "1100") == 0) {
            strcat(newXOR, "C");
        } else if(strcmp(strXORED, "1101") == 0) {
            strcat(newXOR, "D");
        } else if(strcmp(strXORED, "1110") == 0) {
            strcat(newXOR, "E");
        } else if(strcmp(strXORED, "1111") == 0) {
            strcat(newXOR, "F");
        }

    }

    return newXOR;

}

int main(int argc, char* argv[]) {

    if(argc != 3){
        printf("Usage:\n");
        printf("xor HEX1 HEX2\n");
        return 0;
    }

    if(strlen(argv[1]) == strlen(argv[2])) {

        char oneXOR[128];
        char twoXOR[128];
        char newXOR[128];

        strcpy(oneXOR, argv[1]);
        strcpy(twoXOR, argv[2]);
        strcpy(newXOR, "");

        printf("XOR: %s %s\n", oneXOR, twoXOR);
        strcpy(newXOR, xorHash(oneXOR, twoXOR));
        printf("RESULT: %s\n", newXOR);

    }

    return 0;
}
Code
  • 1