# How to XOR two hex values and am I doing crib dragging correctly? (OTP)

Let's say I have the two cipher texts

7ECC555AB95BF6EC605E5F22B772D2B34FF4636340D32FABC29B 73CB4855BE44F6EC60594C2BB47997B60EEE303049CD3CABC29B

According to this website http://xor.pw/? the result of the XOR is

d071d0f071f000000071309030b4505411a5353091e13000000

Is this correct? I don't know as I do not know how to XOR two hex numbers (I assume you turn them into binary but this would become incredibly tedious very fast)

And to further my question, is this the correct way to crib drag?

746865 XOR d071d0
Gives a419b5, which is a non ASCII-Character

Then I would to proceed to move one character down

746865 XOR 071d0f which gives 73756a which in ASCII turns into 'suj' but likely gibberish

and so forth.

Am I correctly doing the procedure?

• Does it matter if a leading zero is removed? I didnt actually know that – Kamijou Mar 5 '16 at 22:44
• Ive actually been trying to solve this for two days... any tips? Ive used so many key words but I keep seem to be getting jibberish after xoring – Kamijou Mar 5 '16 at 22:47
• I will write an answer. And remove my upper comments. – thepacker Mar 5 '16 at 22:49

7ECC555AB95BF6EC605E5F22B772D2B34FF4636340D32FABC29B

73CB4855BE44F6EC60594C2BB47997B60EEE303049CD3CABC29B

0D071..... As the page told you.

Xoring is a so called modulo 2 addition without carry bit propagation. You are adding each bit with the corresponding bit of the other string. First you convert your hexadecimal representation into binary. Then you perform the modulo 2 addition. (dots are for better readability)

7ECC5 becomes 0111.1110.1100.1100.0101
73CB4 becomes 0111.0011.1100.1011.0100
--------------------------------------
XOR
--------------------------------------
0000.1101.0000.0111.0001
which is converted into
0    D    0    7    1


PS:

Apply the following rules for adding each bit.

0 xor 0 = 0
0 xor 1 = 1
1 xor 0 = 1
1 xor 1 = 0

• Is E+3 a mistake? 1110 + 0011 should be 0001 – Kamijou Mar 5 '16 at 23:02
• No it is not. It should be 1101 as written above. Do not add mod 16 but add bitwise. – thepacker Mar 5 '16 at 23:03
• I see, with regards to the crib dragging, do you have any tips for that? I cant seem to get it – Kamijou Mar 5 '16 at 23:16

Thepacker has already described how bitwise XOR on hexadecimal digits works. I would simply like to add a practical suggestion: instead of trying to do crib dragging by hand, learn a programming language and let it do the work for you.

Pretty much any programming language will do; I would personally suggest Python as a good choice for a first language to learn, but e.g. Ruby or Perl or Java or even C or C++ would also work, as would literally dozens of other languages. You will probably want to pick up a good introductory book (or e-book or online course) on Python (or some other language) for new programmers, like one of those listed on this page. Apparently, there's even a book written specifically for new programmers about breaking simple ciphers with Python!

Yes, it will take you a few days or weeks or months to get up to speed with programming, but you should still do it. The main reason is that, as you get further into your crypto studies, you're going to run into more and more stuff that you'll really want to automate, and there will not always (or even usually) be any pre-made tool that does exactly what you want. And, of course, once you get into modern crypto, programming becomes an absolutely essential part of it.

Ps. As a teaser, here's a quick Python program to do your crib dragging exercise:

ciphertextA = bytearray.fromhex("7ECC555AB95BF6EC605E5F22B772D2B34FF4636340D32FABC29B")
ciphertextB = bytearray.fromhex("73CB4855BE44F6EC60594C2BB47997B60EEE303049CD3CABC29B")
xored = bytearray(a^b for a,b in zip(ciphertextA, ciphertextB))
crib = bytearray(b" the ")

for offset in range(0, len(xored) - len(crib) + 1):
piece = xored[offset : offset + len(crib)]
piece = bytearray(a^b for a,b in zip(crib, piece))
if all(32 <= c <= 126 for c in piece):
piece = ("." * offset) + piece.decode('ascii') + ("." * (len(xored) - len(crib) - offset))
print("%3d %s" % (offset, piece))


and its output:

  0 -suj'.....................
1 .'igb?....................
2 ..={oz ...................
3 .../swe ..................
4 ....'khe .................
5 .....?the'................
6 ...... thb3...............
7 ....... tov)..............
8 ........ s{l#.............
9 .........'gaf+............
10 ..........3}kne...........
11 ...........)wc %..........
13 .............+1m\$:........
15 ...............%5r6s......
16 ................an;6).....
17 .................:';l>....
18 ..................s'a{3...
19 ...................s}vv ..
20 ....................)j{e .
21 .....................>ghe


By the way, as you might be able to tell from the output above, you're going to have a hard time fully decoding these messages if all you have are the two ciphertexts given above. That's because there are several parts where multiple successive bytes of the ciphertexts are identical, so that all you can tell about those parts of the plaintexts is that they, too, must be identical. Without knowing the key, however, it may be difficult or impossible to tell exactly what those identical parts of the plaintexts should actually contain.