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

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

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.

Encryption and Decryption with a String key - JAVA

I want to write one way to encrypt some data with a String key which is the best approach?
Encode and decode A string with Key. Suppose you have a string "ABCD" and a key "BC" then the output should be "BDDF".
Can some please guide me with this question?
Depends what level of security do you want
what you have described is a simple polyalphabetic substitution cipher and provides very little actual security (though it is a nice learning example, history lesson and good excercise trying to learn how to break it).
In that case you may have a finite group (an array) of characters and work with remainderless addition. Simple and working.
if you want to encrypt something more serious way, you may look for serious cryptography (in your case you need as well a pbkdf - password based key derivation function).
I have written a small tutorial you may have a look at

Representing a string uniquely using hashCode [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am trying to create a zookeeper node with unix path as values(like /x/home/rrs/data0) , but this is not allowed.
So I thought of generating a hash code of path and then use it to create a node.
But I read following about the hashcode:
Hash should not be used in a distributed application.
There might be collisions, For example, the Strings "Aa" and "BB" produce the same hashCode: 2112
Should i go ahead with hash code or What other options i have for my use case?
Also if i keep the string same all the time , is it guaranteed to generate same hashCode every time?
Yes, the same string will always generate the same hash-code.
Hash-codes do collide, the chance that similar (but different) strings will collide is just very very small (that's the generic idea). Your application should be able to recover (at least not break) from a collision.
What are the nature of the strings? Are they only letters? Maximum length? These properties can be used to generate a better hashcode. One of the nicest techniques I know of is Zobrist keys. Depending on the nature of your strings, this may be an option.
This depends on what you are trying to do.
But you're right: Java hashCodes are not designed to be collision free.
If you need some kind of unique identifier you could use a cryptographic hash function (like e.g. SHA-256, MD5 etc.) over your string.
If you just have a problem with some characters in your string just replace them e.g. with underscore.
Depending on what Zookeeper is/does perhaps hashCode is not a problem at all. EHCache uses it and it's perfectly fine there for distibuted hash tables.
It's a pitty, but hashCode of String really does generate the same hash code all the time for the same string. This is because it is documented and therefore cannot be changed. (But note: this doesn't include different representations of the same string like it's possible in unicode. But I think this is not a problem here.)

Cryptanalysis: XOR of two plaintext files

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.

Making a line of code difficult to read

Im writing a way of checking if a customers serial number matches my hard coded number. Is there a way of making this as hard to read as possible in case an undesirable gets their hands on the code?
I am working in java.
For instance (pseudo code)
if (x != y) jump out of code and return error
Cheers , apologies if this is a bit of an odd one
Security through obscurity is always a bad idea. You don't need to avoid it, but you should not trust solely on it.
Either encrypt your serials with a key you type in at startup of the service, or just specify the serials as hex or base64, not ASCII.
The normal way to do this would be to use a hash.
Create a hash of your serial code.
To validate the client serial, hash that using the same function.
If the hashes match, the serial was correct, even though the serial itself was not in the code.
By definition, a from the hash it's almost impossible to deduce the original code.
Making the code look complex to avoid being hacked never helps!
You can try SHA1 or some other one-way encrypting (MD5 not so secure but it's pretty good). Don't do this:
if (userPassword equals myHardCodedpassword)
Do this:
if (ENCRYPTED(userPassword) equals myhardcodedEncryptedpassword)
So the code-reader only can see an encrypted (and very very very difficult to decrypt) value.
Tangle the control structure of the released code?
e.g feed the numbers in at a random point in the code under a different variable and at some random point make them equal x and y?
http://en.wikipedia.org/wiki/Spaghetti_code
There is a wikipedia article on code obfuscation. Maybe the tricks there can help you =)
Instead of trying to make the code complex, you can implement other methods which will not expose your hard-coded serial number.
Try storing the hard coded number at some permanent location as encrypted byte array. That way its not readable. For comparison encrypt the client serial code with same algorithm and compare.

Categories

Resources