Choosing a encryption key from Diffie-Hellman output - java

I implemented Diffie–Hellman key exchange in Java with some large groups from RFC 3526. My output is a fairly large array of bytes. Is it safe to use the first 448 bits (56 bytes) of the output for a blowfish key? Should I transform the bytes in any way, or pick any specific bytes for the key?

From a theoretical point of view, no, it is not safe. Not that I could pinpoint an actual attack; but the output of a Diffie-Hellman key exchange is an element of a group consisting in q elements and offering sqrt(q) security at most. Truncating parts of the encoding of that element does not look like a good idea...
The "proper" way is to use a one-way key derivation function. In simple words, process the Diffie-Hellman output with a good hash function such as SHA-256 and use the hash result as key. Hashing time will be negligible with regards to the Diffie-Hellman step. Java already includes fine implementations of SHA-256 and SHA-512, and if you are after compatibility with very old Java implementations (e.g. the Microsoft JVM which was coming with Internet Explorer 5.5) then you can use an independent Java implementation of SHA-2 such as the one in sphlib. Or possibly reimplement it from the spec (that's not hard): FIPS 180-3 (a PDF file).
If you need more than 128 bits for your key then this means that you are a time-traveler from year 2050 or so; 128 bits are (much) more than enough to protect you for the time being, assuming that you use a proper symmetric encryption scheme.
Speaking of which: Blowfish is not really recommended anymore. It has 64-bit blocks, which implies trouble when the encrypted data length reaches a few gigabytes, a size which is not that big nowadays. You would be better off using a 128-bit block cipher such as the AES. Also, in any serious symmetric encryption system you will need a keyed integrity check. This can be done with a MAC (Message Authentication Code) such as HMAC, itself built over a hash function (then again, easy to implement, and there is a Java implementation in sphlib). Or, even better, use the AES in a combined encryption/MAC mode which will handle the tricky details for you (because using a block cipher properly is not easy); lookup CWC and GCM (both are patent-free; the latter has been approved by NIST).

The solution that you propose depends on whether the most significant bits of a Diffie-Hellman exchange are hard core. There are some small results known that show that the most significant bits are unpredictable, but I'm not aware of a paper that is strong enough to show that your approach is correct.
However, there are several proposals for a key derivation from Diffie-Hellman keys.
E.g. a nice paper is NIST SP 800-135. So far this is only a draft and can be found here. However, it reviews some existing standards. Of course, using a standard is always preferable to develop it yourself.
While Thomas Pornin's proposal looks reasonable it is nonetheless an ad hoc solution. And to be on the safe side you should probably not use it. Rather I'd use something that has been analyzed (e.g. the key derivation scheme use in TLS version 1.2).

Related

Find message from hash?

I recently read that MD5 is not secure because it can be traced within a small amount of time.
If I give only a fixed 512 bit data as input.
MD5 will give 128 bit hash (32 hex values)
If MD5 is flawed, then can anyone suggest the best way to reconstruct the 512 bit input, given the 128 bit hash?
(Side note: I badly want to implement this. Would C++ be a better choice for speed or Java for its inbuilt security packages?)
There are 2 ** 384 (about 4x10**115) different 512-bit blocks that hash to the same MD5. Reversing isn't possible even in principle.
It is possible, however, to find one of those 4x10**115 blocks that produces the same MD5 as the block you want, and that's why it's considered insecure. For example, if you posted a file to the net along with an MD5 hash to verify its integrity, a hacker might be able to replace it with a different file with the same hash.
With a more secure hash like SHA256, even this wouldn't be possible.
MD5 is simple and fast algorithm especially when implemented using GPU, so it can be cracked by brute force that is why it is not 'secure'.
But the typical context in which it is insecure is in the respect of passwords which have limited number of characters and their typical combinations (dictionary worlds)
For 512bit long message the brute force would take too long even with MD5, it is equivalent to 64 characters passwords, currently the brute force attack limit is around 10 characters.

Creative/secure ways to protect data based on a shared secret in Java

I've been experimenting with some basic cryptography techniques in Java (my preferred programming language) and have a simple example that uses modular exponentiation to generate a shared secret between two client pairs.
But, given a shared secret, what are some simple-to-implement (yet secure) methods for actually using this secret to encrypt/decrypt or scramble/unscramble data being sent over the wire?
For example, if I have the String:
"So long, and thanks for all the fish"
And the shared secret (BigInteger):
1110278255331388386297296974141977
How can the String be sent over the wire in a way that allows for the clients to understand each other, while ensuring that without the shared secret, no middle man can interpret it?
I'm not asking for a finished implementation, just ideas or references to algorithms/techniques that can be used. I'm also avoiding relying on existing programs or APIs (like public/private keys) since this is just a side project for my own educational purposes.
There is a standard way of doing what you are after and that is called password-based key derivation. You need to use a secure symmetric encryption algorithm. You can of course go for asymmetric ones like RSA, but with a shared secret, that is redundant.
However, you don't want to use your shared secret directly.
Your shared secret may have an inappropriate size to be used as a key. For example, AES, as a good choice, accepts 128-bit and 256-bit keys and the shared secret may not be a good match.
The key for your symmetric algorithm of choice should be secure enough, which means that it should have a secure level of randomness which your shared secret may lack.
This is exactly the case algorithms like PBKDF2 (password-based key derivation function 2) are invented for. PBKDF2 is already implemented in standard java and you may use it. It generates a secure key with arbitrary size based on a "passphrase", which is simply the shared secret in this case. These family of algorithms have a iteration parameter, which indicates how many times a hash function is applied to derive the key. Make sure to set it to a high number like a few thousand.
I should note though that security (confidentiality and integrity of transmitted data) in this cases relies on your shared secret to be actually secret. I don't know how you are generating it, but you need to make sure that the process is secure. Diffie-Hellman Key Exchange is a good example. If you are not familiar with this, I recommend you to take a look and see what is does to ensure that the process is safe.
As it is already stated in the comments, you don't need to (and also should not) innovate in cryptography for a practical application. You will find anything you need already implemented and proven secure. Take my last sentence with a grain of salt though.

Is it safe to pass the modulus of RSA key through Java Socket connection without encryption?

I'm building a server application in Java that servers clients which are built in Flash using AS3. The as3crypto library needs the modulus of the RSA key in order to do the encryption, so I was thinking to pass the modulus of the key from the server to the client. Is it safe to do that without encrypting the key?
First, SSL/TLS would be a better choice, since it is already a robust (TLS 1.1) protocol, and not something made up. Secondly, passing the modulus is ok. At least, it should be. If you are using RSA properly, your Modulus should be composed of two primes, each one at least 1024bits long. You only have to be really careful what exactly you pass. There are two parts of an RSA (Public Crypto System) key. One public, one private. In RSA you can only pass the product of your primes though an open channel (this provides NO authentication at ALL). Not the exponent. You can't encrypt your modulus, because then you would have to crack the second envelope and would still get to your modulus, which only shifts the problem to knowing the outer modulus.
I have to admit, using a TLS layer would make you much safer. Use something that is already there, and if you really want to have your own protocol, yes, you can pass the Modulus safely. (In most cases. Although in cryptography, there is never any guarantee that any protocol is robust)

How to use Skipjack (skip32) in Java to randomize sequential integers from a database

Based on a previous question, I am using a sequential integer as a record ID in my database. I want to obfuscate the integer IDs using Skip32. I found a Java implementation but I am uncertain of how to initialize it using the standard JCE APIs. I need to encrypt an integer and decrypt it as necessary. Can anyone show me an example of this?
The code you found belongs to the Cryptix project. You need not just this one file, but you should take the whole package. Take the JCE package, install it as a provider. Then you should be able to use
Cipher c = Cipher.getInstance("SKIPJACK");
But actually, instead of using an unsupported library like Cryptix, using the BouncyCastle library (or parts thereof) might be more recommendable. They have lots of documentation, and a SkipJack-implementation, too.
I'm not sure why you would need to use Skipjack instead of any cipher which comes with your JRE, though - just for the smaller block size?
If I understand right, Skip32 is a separate cipher (working on 4-byte blocks), just build by similar principles like Skipjack (which works on 8-byte blocks). I didn't find any specification of it, only some C and Perl source code, so I doubt there will be some Java implementation available. Have a look at Format-preserving encryption on Wikipedia, or Can you create a strong blockcipher with small blocksize, given a strong blockcipher of conventional blocksize? on Cryptography Stack Exchange, which show other ways of building a small-block cipher from a larger one.
You might find this blog post on secure permutations with block ciphers useful in figuring out how to implement it. Any block cipher with a sufficiently short block size will suffice.

What are the pros and cons of various AES variants in the Java Cryptography Extension?

Various examples I've seen use "AES/CBC/PKCS7Padding" when I get a cypher instance. Obviously AES is the crypto algorithm, what is CBC? What are the pros and cons of various different padding approaches like PKCS7Padding?
I wish to use this to encrypt individual UDP packets end-to-end - any reason that would be unwise?
As far as the CBC mode of operation is concerned, it is recommended to use it in place of ECB when possible. Especially on plain text encryption, or data that repeat a lot. (Network protocols obviously belong to this category)
The ECB (Electronic Code Block) process each block independently. Thus identical blocks will be encrypted identically for each occurrence in the stream. With CCB (Cipher Block Chaining) the state of the previous block encryption is propagated, then identical block are coded with a different salt which makes the result differs from one to another occurrence of an identical block.
On the padding thing. The objective is to be able to unambiguously remove the padding in the decrypt process. I did not go through the "why" one is better than an other, but I you can find some explanation in Niels Ferguson and Bruce Schneier book since they recommend PKCS padding or the 0x80 0x00 ... padding.
Take care when using your AES over multiple languages and/or cryptographic librairies. In fact, implementations seem to differ a lot for that single algorithm. Sometimes, it's just default parameters, sometimes there are no other parameters.
CBC: see http://en.wikipedia.org/wiki/Cipher_block_chaining

Categories

Resources