XOR encrypted string - decryption problem

Hey, I have an problem with decrypting XOR encrypted string (every char is encrypted and appended to string). I have an "key", what original string was and the final "string" (arabic chars) but even with that info I have an problem (some chars doesnt match, "comma" every char and "-n" instead of "dot").

Can somebody take a look? First time doing something bitewise, maybe I misunderstood something.

Code should print "slash" (/) but printing -o

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <windows.h>
#include <string>

std::string decrypt(std::string value){
    std::string final;
    int i = 0;
    while (i < value.size()){
        final.push_back((char)value.at(i) ^ 0x6F6);
        ++i;
    }
    return final;
}

int main()
{
    std::cout << decrypt("ۙ") << std::endl;
    return 0;
}
Last edited on
You're XOR'ing a char which is likely not what you want because of sign bit.

Can you show encryption function? doe encryption involve logical shift?
xor encryption produces binary (as in binary files: every possible byte is allowed).
I have not spent a lot of time trying to shovel the unprintables into std::string but you are going to get stuff like char 0-20 which in ascii are a mix of things that should not be printed.

I would try a vector of unsigned char instead of a string here.
and print that one char at a time in hex to see the encrypted data, or one letter at a time in ascii but be prepared for oddities when you do it.

then decrypt the vector, and you can dump that result back into a string (stuff a 0 char on the end of it like a c-string and vector can convert it from c-string to printable again).

If this is for any practical use, a constant key is very easily broken. Once you have it working, use <random> bytes and generate the random stream seed from the password/key/something.
Last edited on
I dont have now encryption function but I know which "encrypted string" should print what output.

Original decryption function is made in Java:

1
2
3
4
5
6
7
8
9
    private static String decrypt(String value) {
        StringBuilder builder = new StringBuilder();
        int n = 0;
        while (n < value.length()) {
            builder.append((char)(value.charAt(n) ^ 0x6F6));
            ++n;
        }
        return builder.toString();
    }


I know XOR String encryption is not really good protection but I just want to learn something with bitewise.
wait... you sent empty string to decrypt? I missed that before.
the while loop does not execute in c++ for empty string.
.at is slow. if you can use [] instead, you should, and here, you know your index is safe and in range.

try this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

std::string crypt(std::string value) //xor self reverses, so encrypt and decrypt are same function
{    
     for(auto &c : value) //for every letter in value, alias that as 'c' 
    {
        c ^= 0x6F6;  //we modify c, which modifies value, but value is a copy of what was sent. 
    }
    return value; //the copy.  the original in main is unchanged. 
}

int main()
{
    string o{"abc"};	//non empty string
    string s = crypt(o);  //so we can check original
    cout << "orig: " << o << endl; //unchanged by function verified
    std::cout << s << std::endl; //unprintable nonsense, but it worked
	s = crypt(s);  //do we get abc back when we call it again?
    std::cout << s << std::endl;
    return 0;
}


sending "" (empty string) is still not going to do anything meaningful.
I ran it with some punctuation, numbers, etc and it still works and it prints junk for the junk characters...

C:\c>a
orig: azAZ19!)~.,
□□□□□□□߈□□
azAZ19!)~.,
Last edited on
Or try this. On the Java code I can get: "AES"

The result should be:
String: "ԈԌԚ"
Key: 1353
Result: "AES"


but Im getting: "¥┴¥┼¥╙"

what is key?
is "AES" your test case?

a quick google tells me that
The representation for String and StringBuilder etc in Java is UTF-16

but you are using ascii (utf-8 I guess?) for this C++ code.

you can try wstring in c++...
(which needs wcout). L"string" is widened for a literal.
But I have not been able to get your 'expected' results.
If the goal is to duplicate java, it will take a bit of unraveling what java is doing vs what c++ is doing. I can assure you that a^b works the same in both, assuming both are unsigned (which java is wonky about). So if you can get it down to the same a & b for both languages, it WILL work, but that means understanding both languages well.

you are not doing anything 'wrong', you are just fighting a language translation issue.
Last edited on
Topic archived. No new replies allowed.