Cryptanalysis: XOR of two plaintext files - java

I have a file which contains the result of two XORed plaintext files. How do I attack this file in order to decrypt either of the plaintext files? I have searched quite a bit, but could not find any answers. Thanks!
EDIT:
Well, I also have the two ciphertexts which i XORed to get the XOR of the two plaintexts. The reason I ask this question, is because, according to Bruce Schneier, pg. 198, Applied Cryptography, 1996 "...she can XOR them together and get two plaintext messages XORed with each other. This is easy to break, and then she can XOR one of the plaintexts with the ciphertext to get the keystream." (This is in relation to a simple stream cipher) But beyond that he provided no explanation. Which is why I asked here. Forgive my ignorance.
Also, the algorithm used is a simple one, and a symmetric key is used whose length is 3.
FURTHER EDIT:
I forgot to add: Im assuming that a simple stream cipher was used for encryption.

I'm no cryptanalyst, but if you know something about the characteristics of the files you might have a chance.
For example, lets assume that you know that both original plaintexts:
contain plain ASCII English text
are articles about sports (or whatever)
Given those 2 pieces of information, one approach you might take is to scan through the ciphertext 'decrypting' using words that you might expect to be in them, such as "football", "player", "score", etc. Perform the decryption using "football" at position 0 of the ciphertext, then at position 1, then 2 and so on.
If the result of decrypting a sequence of bytes appears to be a word or word fragment, then you have a good chance that you've found plaintext from both files. That may give you a clue as to some surrounding plaintext, and you can see if that results in a sensible decryption. And so on.
Repeat this process with other words/phrases/fragments that you might expect to be in the plaintexts.
In response to your question's edit: what Schneier is talking about is that if someone has 2 ciphertexts that have been XOR encrypted using the same key, XORing those ciphertexts will 'cancel out' the keystream, since:
(A ^ k) - ciphertext of A
(B ^ k) - ciphertext of B
(A ^ k) ^ (B ^ k) - the two ciphertexts XOR'ed together which simplifies to:
A ^ B ^ k ^ k - which continues to simplify to
A ^ B ^ 0
A ^ B
So now, the attacker has a new ciphertext that's composed only of the two plaintexts. If the attacker knows one of the plaintexts (say the attacker has legitimate access to A, but not B), that can be used to recover the other plaintext:
A ^ (A ^ B)
(A ^ A) ^ B
0 ^ B
B
Now the attacker has the plaintext for B.
It's actually worse than this - if the attacker has A and the ciphertext for A then he can recover the keystream already.
But, the guessing approach I gave above is a variant of the above with the attacker using (hopefully good) guesses instead of a known plaintext. Obviously it's not as easy, but it's the same concept, and it can be done without starting with known plaintext. Now the attacker has a ciphertext that 'tells' him when he's correctly guessed some plaintext (because it results in other plaintext from the decryption). So even if the key used in the original XOR operation is random gibberish, an attacker can use the file that has that random gibberish 'removed' to gain information when he's making educated guesses.

You need to take advantage of the fact that both files are plain text. There is a lot of implications which can be derived from that fact. Assuming that both texts are English texts, you can use fact that some letters are much more popular than the others. See this article.
Another hint is to note the structure of correct English text. For example, every time one statements ends, and next begins you there is a (dot, space, capital letter) sequence.
Note that in ASCII code, space is binary "0010 0000" and changing that bit in a letter will change the letter case (lower to upper and vice versa). There will be a lot of XORing using space, if both files are plain text, right?
Analyse printable characters table on this page.
Also, at the end you can use spell checker.
I know I didn't provide a solution for your question.
I just gave you some hints. Have fun, and please share your findings.
It's really an interesting task.

That is interesting. The Schneier book does indeed say that it is easy to break this. And then he kind of leaves it hanging at that. I guess you have to leave some exercises up to the reader!
There is an article by Dawson and Nielson that apparently describes an automated process for this task for text files. It's a bit on the $$ side to buy the single article. However, a second paper titled A Natural Language Approach to Automated Cryptanalysis
of Two-time Pads references the Dawson and Nielsen work and describes some assumptions they made (primarily that the text was limited to 27 characters). But this second paper appears to be freely available and describes their own system. I don't know for sure that it is free, but it is openly available on a Johns Hopkins University server.
That paper is about 10 pages long and looks interesting. I don't have time to read it at the moment but may later. I find it interesting (and telling) that it takes a 10 page paper to describe a task that another cryptographer describes as "easy".

I don't think you can - not without knowing anything about the structure of the two files.

Unless you have one of the plaintext files, you can't get the original information of the other. Mathematically expressed:
p1 XOR p2 = en
You have one equation with two unknowns, you can't possibly get something meaningful out of it.

Related

Is this way of generating a securerandom biginteger secure?

So I tried this line of code in java which generates a random integer that is 40 bytes long. I have no clue if it's secure and I wondered if anyone with a little bit more experience than me could explain.
I would like to know if this is cryptographically secure. meaning is this a secure way of generating a random number that's a BigInteger. If it isn't secure what would be a good way to generate a full cryptographically random BigInteger.
SecureRandom random = new SecureRandom();
BigInteger key_limit = new BigInteger("10000000000000000000000000000000000000000");
int key_length = key_limit.bitLength();
BigInteger key_1 = new BigInteger(key_length, random);
You're rolling your own crypto.
Be prepared to fail. The odds that the code you end up writing will actually be secure are infinitesemal. It is very, very, very easy to make a mistake. These mistakes are almost always extremely hard to test for (for example, your algorithm may leak information based on how long it takes to process different input, thus letting an attacker figure out the key in a matter of hours. Did you plan on writing a test that checks if all attempts to decode anything, be it the actual ciphertext, mangled ciphertext, half of ciphertext, crafted input specifically designed to try to derive key info by checking how long it takes to process, and random gobbledygook all take exactly equally long? Do you know what kind of crafted inputs you need to test for, even?)
On the topic of timing attacks, specifically, once you write BigInteger, you've almost certainly lost the game. It's virtually impossible to write an algorithm based on BI that is impervious to timing attacks.
An expert would keep all key and crypto algorithm intermediates in byte[] form.
So, you're doing it wrong. Do not roll your own crypto, you'll mess it up. Use existing algorithms.
If you really, really, really want to go down this road, you need to learn, a lot, before you even start. Begin by analysing a ton of existing implementations. Try to grok every line, try to grok every move. For example, a password hash checking algorithm might contain this code:
public boolean isEqual(byte[] a, byte[] b) {
if (a.length != b.length) throw new IllegalArgumentException("mismatched lengths");
int len = a.length;
boolean pass = true;
for (int i = 0; i < len; i++) {
if (a[i] != b[i]) pass = false;
}
return pass;
}
and you may simply conclude: Eh. Weird. I guess they copied it from C or something, or they just didn't know they could have removed that method entirely and just replaced it with java.util.Arrays.equals(a, b);. Oh well, it doesn't matter.
and you would be wrong - that's what I mean by understand it all. Assume no mistakes are made. Arrays.equals can be timing-attacked (the amount of time it takes for it to run tells you something: The earlier the mismatch, the faster it returns. This method takes the same time, but only 'works' if the two inputs are equal in length, so it throws instead of returning the seemingly obvious false if that happens).
If you spend that much time analysing them all, you'll have covered this question a few times over.
So, with all that context:
This answer is a bazooka. You WILL blow your foot off. You do not want to write this code. You do not want to do what you are trying to do. BigInteger is the wrong approach.
new BigInteger(8 * 40, secureRandom); will get the job done properly: Generates a random number between (0 and 2^320-1), inclusive, precisely 40 bytes worth. No more, no less.
40 bytes worth of randomness can be generated as follows:
byte[] key = new byte[40];
secureRandom.nextBytes(key);
But this is, really, still a grave error unless you really, really, really know what you are doing (try finding an existing implementation that has some reliable author or has been reviewed by an expert).
You will get a BigInteger containing a securely generated random number that way.
However, that method for calculating the bit length is (to say the least) odd. I don't know about you, but most programmers would find it difficult to work out how many zeros there are in that string. Then, the computation is going to give you a bit count such that 2bits is less than the number.
It would make a lot more sense (to me) to just specify a bit count directly and code it, and add a comment to explain it.
To a first approximation1 2(10*N) is 1000N. However, the former is slightly greater than the latter. That means if your code is intended to give you 40 byte random keys, your computed key length will be off by one.
1 - Experienced programmers remember that ... and inexperienced programmers can use a programmer's calculator.

Is my encryption safe?

I made a own encryption and I would like to know wether it is safe or not.
First of all, its written in Java.
I started with this String:
"Never gonna give you up, never gonna let you down"
it ends as a byte array when encrypted, but for visualizing, I changed it to hexadecimal.
"6b4053405705424a4b4b4405424c5340055c4a5005505509054b4053405705424a4b4b4405494051055c4a5005414a524b"
now is it safe or should i rethink?
Converting each pair of characters as a byte value to ascii gives
k#S#W BJKKD BLS# \JP PU K#S#W BJKKD I#Q \JP AJRK
which is just a simple substitution cipher.
They have these in the newspaper, and people solve them with a pen and paper.

How to make a simple public-key cryptographic algorithm? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I want to make a simple public-key(asymmetric) encryption. It doesn't have the be secure, I just want to understand the concepts behind them. For instance, I know simple symmetric ciphers can be made with an XOR. I saw in a thread on stackexchange that you need to use trapdoor functions, but I can't find much about them. I want to say, take a group of bytes, and be able to split them someway to get a public/private key. I get the ideas of a shared secret. Say, I generate the random number of 256(not random at all :P), and I split it into 200 and 56. If I do an XOR with 200, I can only decrypt with 200. I want to be able to split numbers random and such to be able to do it asymmetrically.
OK, just a simple demo-idea, based on adding/modulo operation.
Lets say we have a modulo value, for our example 256. This is a public-known, common value.
Let's say you generate a random secret private key in the interval [1-255], for example, pri=133.
Keep secret key in the pocket.
Generate a public key, pub = 256 - pri = 123. This public key (123)
you can share to the world.
Imagine, 3rd party does not know, how to compute the private key from a public. So, they know only public key (123).
Someone from the public wants to send you an encrypted ASCII-byte. He gets his byte, and adds to it the public key by modulo 256 operation:
encrypted = (input_value + pub) % modulto;
For example, I want to send you the letter "X", ASCII code = 88 in encrypted form.
So, I compute:
(88 + 123) % 256 = 211;
I am sending you the value 211 - encrypted byte.
You decrypt it by the same scheme with your private key:
decrypted = (input_value + pri) % 256 = (211 + 133) % 256 = 88;
Of course, using the simple generation pair in this example is weak, because of
the well-known algorithm for generating the private key from the public, and anybody can easily recover the private using the modulo and public.
But, in real cryptography, this algorithm is not known. But, theoretically,
it can be discovered in future.
This is an area of pure mathematics, there's a book called "the mathematics of cyphers" it's quite short but a good introduction. I do suggest you stay away from implementing your own though, especially in Java (you want a compiler that targets a real machine for the kind of maths involved, and optimises accordingly). You should ask about this on the math or computer-science stack-exchanges.
I did get a downvote, so I want to clarify. I'm not being heartless but cyphers are firmly in the domain of mathematics, not programming (even if it is discreet maths, or the mathsy side of comp-sci) it requires a good understanding of algebraic structures, some statistics, it's certainly a fascinating area and I encourage you to read. I do mean the above though, don't use anything you make, the people who "invent" these cyphers have forgotten more than you or I know, implement exactly what they say at most. In Java you ought to expect a really poor throughput btw. Optimisations involving register pressure and allocation pay huge dividends in cypher throughput. Java is stack-based for starters.
Addendum (circa 6 years on)
Java has improved in some areas now (I have a compiler fetish, it's proper weird) however looking back I was right but for the sort-of wrong reasons, Java is much easier to attack through timing, I've seen some great use of relying on tracing compiling techniques to work out what version of software is being used for example. It's also really hard to deal with Spectre which isn't going away any time soon (I like caches.... I feel dirty saying that now)
HOWEVER: above all, don't do this yourself! Toy with it AT MOST - it's very much in the domain of mathematics, and I must say it's probably better done on paper, unless you like admiring a terminal with digits spewn all over it.
http://en.wikipedia.org/wiki/RSA_(algorithm)
Is the standard one on which the (whole) internet is based

Why do I sometimes get different SHA256 hashes in Java and PHP?

So I have an odd little problem with the hashing function in PHP. It only happens some of the time, which is what is confusing me. Essentially, I have a Java app and a PHP page, both of which calculate the SHA256 of the same string. There hasn't been any issues across the two, as they calculate the same hash (generally). The one exception is that every once in a while, PHP's output is one character longer than Java's.
I have this code in PHP:
$token = $_GET["token"];
$token = hash("sha256", $token."<salt>");
echo "Your token is " . $token;
99% of the time, I get the right hash. But every once in a while, I get something like this (space added to show the difference):
26be60ec9a36f217df83834939cbefa33ac798776977c1970f6c38ba1cf92e92 # PHP
26be60ec9a36f217df83834939cbefa33ac798776977c197 f6c38ba1cf92e92 # Java
As you can see, they're nearly identical. But the top one (computed by PHP) has one more 0 for some reason. I haven't really noticed a rhyme or reason to it, but it's certainly stumped me. I've tried thinking of things like the wrong encoding, or wrong return value, but none of them really explain why they're almost identical except for that one character.
Any help on this issue would be much appreciated.
EDIT: The space is only in the bottom one to highlight where the extra 0 is. The actual hash has no space, and is indeed a valid hash, as it's the same one that Java produces.
EDIT2: Sorry about that. I checked the lengths with Notepad++, and since it's different than my normal text editor, I misread the length by 1. So yes, the top one is indeed right. Which means that it's a bug in my Java code. I'm going to explore Ignacio's answer and get back to you.
The top hash is the correct length; the bottom hash is output because the hexadecimal values were not zero-filled on output (note that it's the MSn of a byte). So, a bug in the Java program unrelated to the hash algorithm.
>>> '%04x %02x%02x %x%x' % (0x1201, 0x12, 0x01, 0x12, 0x01)
'1201 1201 121'
Actually it's the SECOND hash which seems to have an incorrect length (63). Could it be that it is generated by assembling two different tokens, and maybe the last one - which should be 16 characters - gets the initial zero removed?

Cryptanalysis of ciphertext using Java

I'm looking for some ideas on an assignment.
I have 7 ciphertext files, all of which are encrypted using the same symmetric key, which is 3 characters long and is alphabetic. No encryption algorithm is provided but the specs state that it is a home-made algorithm and is naive (whatever that means). My objective is to decrypt these files. I'm merely looking for ideas on the attacks which I can carry out on these files.
So far, I have done a frequency analysis, brute force attack to detect Ceasar Cipher, Krasinsky's method to detect Vigenere Cipher, Ciphertext XOR to detect a simple version of the stream cipher. I suspect that the files were encrypted using some mix of ciphers.
By the way, the decrypted plaintext is supposed to contain just a plain message, but the ciphertext reveals the use of over 97 different ASCII symbols!
Any general help, ideas or directions are greatly appreciated! Honestly, I'm not expected to decrypt these files, but then I might as well prove my professor wrong with your help. Thanks!
EDIT
I'm looking for attacks on block or stream ciphers. At least thats what I suspect...
The famous Enigma machine used 3 character symmetric alphabetic keys. 97 ASCII symbols? ASCII runs from 32 to 126 giving 94 symbols. The \n and \r add two more for 96 and then an end of message marker such as \0 for 97. To put it another way, a naive copy of the early Engima machines (with a fixed reflector) encrypting Windows style textual data would match the clues very well.
The enigma machine has some known flaws. If your professor was being exceptionally kind he will have replicated the weak system used by the German Navy early on. This was to encrypt every message with a one time key, but then to allow decryption to transmit the one time key twice at the start of the message encrypted using a standard key. By transmitting it twice they provided extra context to the cryptanalysis.
The second well known flaw was that a character never maps to itself. Thus if you have a potential plain text no character will match.
It is possible to brute force Enigma if you know what the rotors and reflector look like. Without knowing that you have around 10^15 possibilities to explore in this case.
Why not go ahead and get started with brute forcing all of the 26**3 possibilities for each of the most popular symmetric key algorithms:
Twofish
Serpent
AES (Rijndael)
Blowfish
CAST5
And any others you can find.
Since the algorithm is simple and homemade, you might try these naive algorithms:
repeated XOR with the cipher key every 3rd character
repeated XOR with the cipher key every 2nd or 1st character
XOR and rotate/shift: the cipher key is xor'ed with the ciphertext and rotated/shifted
Since you know the plain text it to be regular text, look for patterns in the first few characters of ciphertext and see if they can be combined with the cipher key to arrive at a ASCII code for a letter/number.
Now, you said that you have done the statistical analysis. If algorithm is in fact naive, the frequencies of the symbols will not be uniformly distributed. Some symbols will be found more often. Is it the case? If so, I'd dig from there.
I might as well prove my professor
wrong with your help
With "our help" would be us proving your professor wrong.

Categories

Resources