paladium
paladium

Reputation: 21

2 times XOR cypher encryption on file don't yield the same file

I tried to encrypt image file with c++ with XOR encryption . it worked well but when i decrypt it with the same code i can't open the image , i assume they are not the same but in XOR encryption they must be the same

here is the code

void xor_encrypt(std::string const& path) {
    char key[65] = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";
    std::ifstream input{ path,std::ios::binary };
    std::ofstream output;
    output = std::ofstream{ path + ".hafnium", /*added*/ std::ios::binary };

    char buffer[64];

    while (input.read(buffer, 64)) {
        for (size_t i = 0; i < 64; i++) {
            buffer[i] ^= key[i];
        }
        output.write(buffer,/*added*/  input.gcount());
    }

    input.close();
    std::remove(path.c_str());
}

and here the 3 files : original image , encrypted image and encrypted 2 times image

[1] original image : https://i.sstatic.net/VKHKU.jpg [2] image encrypted 1 time : https://mega.nz/file/BUMG2I7K#G3PsUeYCwtTCOj2cYSH47t67_WafRZQsRHyIims-EW0 [3] image encrypted 2 times with xor : https://mega.nz/file/FUMywI5I#mvI6Ge2nEw19fDfTEVso7hKMFSggRJcGJ7_g9178LMQ

the only difference between files i see is that they hasn't the same size

why image encrypted 2 times with xor don't yield the same file ? thanks for answers

EDIT : thanks for answers , it worked well for the image file but when i take other file like a video , it don't work anymore :

original video : https://mega.nz/file/BYU3hQJI#JugOnHZ6_ajnRqHqc18j_j54MqFoIXAUHITSMxbAo48 encrypted video : https://mega.nz/file/JAMFXCRK#DxYqKAvCqda18oC47qOH0Wiec1bmJ7hSlmypczS9LXE encrypted 2 times video : https://mega.nz/file/VVUT1KiA#f0vf43PkEssAmoHuPIcY722kd1p7nvQheIlIwFkmrzk

Upvotes: 2

Views: 398

Answers (2)

&#193;ngel
&#193;ngel

Reputation: 950

dan1st already found the issue of not taking into account the actual number of bytes read, and the mention that you need to process both files in binary mode. It's not a recommendation, if you expect the program to work properly on Windows, you need to do that (you might get away if only handling text, but then an odd file will come and bite you). However, I wanted to note three things.

The first issue I see is that the original file doesn't match. the imgur link doesn't provide the file you used (imgur may have reprocessed it).

Second, the encrypted files are losing bytes. The error of not counting the number of bytes read would make some of your files bigger (they would be padded to 64 bytes, with some plaintext bytes). I suspect this may have been caused by not using binary mode.

And third, you are using the hexadecimal key of 64 characters is doing what you expected. Your key is formed by the characters '9','f','8','6'... You are only xoring a few bits of the file. What you probably wanted to do is to xor with {0x9f, 0x86, 0xd0, 0x81, 0x88...}, i.e. you should be converting the hexadecimal string into bytes and xoring those. It could still be broken quite easily, but it would be the proper way to use this 256 bit-key.

Upvotes: 2

dan1st
dan1st

Reputation: 16338

This is actually some kind of buffer underflow.

The end of the file is the problem.

You read using input.read(buffer, 64) and the last time you execute this, it will likely read less than 64 chars but less.

Then, you still write 64 characters (you just write 64 chars from the array, with the content from before).

Use the following code that writes as much as you read:

while (input.read(buffer, 64)) {
        for (size_t i = 0; i < 64; i++) {
            buffer[i] ^= key[i];
        }
        output.write(buffer, input.gcount());
    }

It uses gcount in order to count the number of characters read.

I would also recommand you writing binary if you have binary input, too.

output = std::ofstream{ path + ".hafnium",std::ios::binary };

Upvotes: 5

Related Questions