Hello everyone,
I am currently developing a chat application and I want to encrypt all send messages. I am using the example below:

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
import java.security.Key;
import java.security.Security;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
public class DESCryptoTest {
    public static void main(String[] args) {
        //Security.addProvider(new com.sun.crypto.provider.SunJCE());
        try {
            KeyGenerator kg = KeyGenerator.getInstance("DES");
            Key key = kg.generateKey();
            
            Cipher cipher = Cipher.getInstance("DES");

            byte[] data = "Hello World!".getBytes();
            System.out.println("Original data : " + new String(data));

            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = cipher.doFinal(data);
            System.out.println("Encrypted data: " + new String(result));

            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] original = cipher.doFinal(result);

            System.out.println("Decrypted data: " + new String(original));
            
            System.out.println("Key : "+ key.toString());

   }

        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        catch (IllegalStateException e) {
            e.printStackTrace();
        }
        catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        catch (BadPaddingException e) {
            e.printStackTrace();
        }
    }
}

But the problem is that I don't know how to save the key, heres it works because its in the same class.

Can someone help me please!! Is there any other way to secure, encrypt message while sending over the network?

Thanks for the answer.

Recommended Answers

All 17 Replies

Can someone help me please!! Is there any other way to secure, encrypt message while sending over the network?

You could use SSL?

No, I want to use an encryption technique! Its for learning purposes. But how to use SSL on a chat program and what is the purpose of this protocol, I just know that its secure, does the SSL layer use some encryption mechanisms?

I still want to know how to use the piece of code above. The problem is just the key, how to store the key, because it keeps on generating a new key, if i can store the Key key then i will be able to continue.


Thanks for the answer. Bye.

yes, SSL/TLS is an enecrypted protocol for key-based data transmission

http://en.wikipedia.org/wiki/Secure_Sockets_Layer

Re: your program. If you just want to save the key why not use the printwriter and stream/buffered reader classes to read/write to a text file.

Have a look at the Preferences class. It allows you to store & retrieve simple strings, ints, booleans etc in a very easy way, without having to bother about the details of where and how they are stored, basically:

Preferences prefs = Preferences.userRoot();
prefs.put(prefsItemName, prefsItemValue);
...
prefs.get(prefsItemName, "");

I'm not networking guy but I may chip in with little.
Any chat application always has server side and client side of application otherwise trying to connect numerous users together would quickly become nightmare. There you will have private encryption key for server and public. There are variety ways of working out public key, but most common is called "handshake" where client after establishing connection send a random number to server and receive unique public key.

I found few examples/resources, they may not be exactly spot on, but hopefully you will find them useful Handshake.java for SSL handshake message in Jessie application, Using JSSE for secure socket communication or this Sun tutorials on Socket Communications and Cryptography. There is also this book Cryptography with Java, but is targeting cryptography and you may not find to much on networking

Hello NeutralFox,

Actually it's good that you cannot save the key. That makes your application more secure - Randomness increases security. All you need is an algorithm to use this evil.

Here is what you can do-
Since your server would be up and running to accept connections, generate a key whenever the server is started. You can save that Key object in the runtime(right?).
Each time a client connects to the server and authenticates, you send the key to the client and to next client and so on as the clients keep coming in.
Generate a new key everytime you bounce the server.

The above method has the following analysis:
Advantages:
1. The key is new everytime the server starts fresh.
2. The key object is to be generated and saved only at runtime and not hardcoded.
3. You can use groups of keys or individual keys or a single key.
4. High performance boost as the message encryption is no longer the network's headache.

Limitations:
1. The first time you send the key, that too needs to be .. hehe.. encrypted.

There is a method to workaround that. If you can think, well and good, else we are always there :)

Regards,
HKansal

Each time a client connects to the server and authenticates, you send the key to the client

As you dont have the key yet, the key would have to be sent unencrypted which means it can be sniffed, defeating the point of the encryption.

As you dont have the key yet, the key would have to be sent unencrypted which means it can be sniffed, defeating the point of the encryption.

I think the only ways round this involve at least one public/private key pair, eg client generates random key (or half a key), encrypts it with server's public key (which it can safely get via a plain-text request) and sends it to the server; only server can decrypt it. The server then generates a random (half) key and sends that back to the client using the client's public key for encryption ditto. Even if the link is totally public, only the client and the server know both random key halves, and are thus able to decrypt messages encrypted using them.
For ultimate security both pairs of public/private keys could be generated from scratch for each session, although this is almost certainly overkill!

As people have mentioned, you need to use asymmetric encryption at the very start of the conversation to send the sessiion key to the server. Use RSA for this. Essentially, you create a public/private RSA key pair as follows:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
      kpg.initialize(2048);
      KeyPair kp = kpg.genKeyPair();
      KeyFactory fact = KeyFactory.getInstance("RSA");
      RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
      RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);

Each of the key spec objects has methods that give you a couple of BigIntegers. Save the private ones in one file and the public ones in another. The private ones are kept secret on your server; the public ones are not secret and are distributed to your clients. Now, when a client needs to start a converstaion, it creates some random bytes that will be the encryption key for that session. Then sends that key to the server by encrypting with an RSA cipher instance, initted with the public key; the server inits its with the private key to decrypt. Then, the rest of the conversation uses a regular symmetric encryption system (e.g. AES) with that key.

Don't use DES: it's slow and insecure. If you've not reason to use anything else, use AES.

Note that there are details you need to think about to make this really secure. With block ciphers such as AES, you must basically make sure you "never encrypt the same thing twice" with the same key. One way to do this is to use the cipher in "counter mode" (there are other modes: google for details). For example:

Cipher c = Cipher.getInstance("AES/CTR/PKCS5NOPADDING");

Call getIV() on the cipher to get the "initialisation vector"-- effectively, the initial value of the counter. Then send this to the server before the beginning of the encrypted data. The server inits its cipher with a corresponding IvParameterSpec.

You also need to think about "replay attacks": an attack where an eavesdropper records the entire encrypted conversation and simply plays it back to the server. So when you first "log in" to the server, it should generate some random "nonce" string of bytes, which at the beginning of the conversation your client will build into the data it encrypts (and the server then checks for and allows only once).

commented: Good Post +7

As you dont have the key yet, the key would have to be sent unencrypted which means it can be sniffed, defeating the point of the encryption.

Hey! Thanks for reiterating my message :)
I love the way you encourage ppl at Dani-Web.

And we ve got a couple of workarounds I see. Nice.

Hello everyone , thanks a lot for your answers ,

Wow .. I've learn so many things, i will try these techniques during the coming days !!

Again, thanks a lot, I will let know if my problem has been solved.

Hello, the reason why I want to save the key : because I want to seperate the encryption and decryption process.

Let say, that the sender encrypt the message using a specific key and the receiver need this key to decrypt the message at the other end.

You see, I just want to have the key ... but the problem is that I am unable to store the key and use it at the other .. thanks.

OK, lets go thru this one more time:
At the server generate a public/private key pair, and store them.
Client connects, requests server's public key.
Client generates a random session key, encrypts it using the server's public key, and sends it to the server.
Server uses its private key to decrypt the session key.
Client and server now use the session key to encrypt all following traffic, starting with a logon etc.

Thanks for the answer James, but the problem is that ... i don't want to use the private/public key. I want to use the example I gave in the first post. I just want to have a way to store the key .. or use the same key to decrypt.

Forget the chat program for the time being. I just want to use DES to encrypt and decrypt file. But the encryption and the decryption should be seperated and for that i must find a way to store the key. Hope you understand my question.

I will surely use the public/private key in the coming weeks but for the time I want to use DES .. its for learning purposes.

Thanks a lot for your answers guys.

If you just want to store the key, use Preferences, like I suggested n posts ago. I understand what you WANT to do, but I really think it's not realistic - you'll have to send the key to the client unencrypted, which is pointless. Still, good luck.

Thanks for the answer, yepp you are right .. but I just want to use DES for some other purposes, just want to know how it works, I am currently working on the FTP part .... in the coming weeks I will surely implement the private/public, if i have enough time of course, again, thanks for the answer.

The key is just a string of random bytes. You can store it any which way you like-- it's just a boring old string of bytes. To actually get the bytes, you have a couple of options:

(1) Just generate the string of random bytes yourself, using SecureRandom, then init your Cipher with a SecretKeySpec wrapper around those bytes:

Random r = new SecureRandom();
      byte[] key = new byte[8];
      r.nextBytes(key);
      c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DES"));

(2) The "proper" way (but slightly overengineered for this purpose) is to use a KeyGenerator to generate the key, then a SecretKeyFactory to convetr it into a keyspec object from which you can pull out the bytes:

KeyGenerator kg = KeyGenerator.getInstance("DES");
      SecretKey k = kg.generateKey();
      SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
      DESKeySpec spec = (DESKeySpec) skf.getKeySpec(k, DESKeySpec.class);
     byte[] keyBytes = spec.getKey();

You can also cheat slightly in this case. If you call getEncoded() on the SecretKey, you'll actually get the selfsame bytes as via the factory.

Strictly, the KeyGenerator is the "correct" way because it is supposed to know about certain weak keys/constraints on key creation for your particular algorithm. As I recall, DES has 4 weak kes out of the total 2^56, so in practice you really don't need to worry. AES (and, ideally, whatever algorithm you pick) has no known weak keys -- you really can just generate a random string of bytes.

Incidentally, I assume you know that DES is not secure by today's standards (actually, it wasn't very secure by yesterday's standards...) and much slower and less secure than practically any other algorithm in the universe. You may be interested in some stuff I've written about Java cryptography, including the security and performance of different algorithms. I'd also recommend you read the stuff about block modes (the example uses AES, but the information leak problem applies to DES too).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.