Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Encryption in Java

I have a text config file. This file needs to be encrypted and shipped with the product so that the end user can not change the values.

I have looked into AES for doing this and come across this simple example.


import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

/**
 * This program generates a AES key, retrieves its raw bytes, and
 * then reinstantiates a AES key from the key bytes.
 * The reinstantiated key is used to initialize a AES cipher for
 * encryption and decryption.
 */
public class AES
{

    /**
     * Turns array of bytes into string
     *
     * @param buf   Array of bytes to convert to hex string
     * @return  Generated hex string
     */
    public static String asHex(byte buf[])
    {
        StringBuilder strbuf = new StringBuilder(buf.length * 2);
        int i;

        for (i = 0; i &lt buf.length; i++)
        {
            if (((int) buf[i] & 0xff) &lt 0x10)
            {
                strbuf.append("0");
            }

            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }

        return strbuf.toString();
    }

    public static void main(String[] args) throws Exception
    {

        String message = "This is just an example";

        // Get the KeyGenerator

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128); // 192 and 256 bits may not be available


        // Generate the secret key specs.
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");


        // Instantiate the cipher

        Cipher cipher = Cipher.getInstance("AES");

        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(message.getBytes());
        System.out.println("encrypted string: " + asHex(encrypted));

        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] original = cipher.doFinal(encrypted);
        String originalString = new String(original);
        System.out.println("Original string: " + originalString + " " + asHex(original));
    }
}


Is this a good approach? I could get the config file as a string, encode it, write the encoded bytes to a file. I could then distribute the encoded file.

On the other end though, how would I decipher it? How to I distribute the key spec so that it will be able to be deciphered?

Thanks

like image 446
user489041 Avatar asked Sep 03 '26 19:09

user489041


1 Answers

(Reposting a slightly abridged version of my comment as an answer, since it got several votes and I am quite convinced that this is the answer.)

You are facing the same problem as the movie and game industries, and the answer is: the best you can do is to make it hard for the user to change the file; you cannot make it impossible. The decryption key must necessarily reside somewhere in your code (or in the hardware, if you produce the hardware too), where it can be obtained by reverse engineering. You could encrypt the key too, but then the second key must be stored in your code, and so on. You'll get a similar problem if you decide to store a hash of the file in your code and use it to verify that the file has not been tampered with, because then someone could alter the hash inside your executable (Edit: or simply alter the code to skip the hash check entirely).

As @limc mentioned, you could go for some central verification scheme, with all the problems and user-hostility they bring. I think @Mr Jacques' suggestion is your best option unless you really need it to be 100% hack-proof (in which case I think you have a big problem), as it will deter the vast majority of users (until someone publishes a crack, that is...)

like image 92
Aasmund Eldhuset Avatar answered Sep 05 '26 07:09

Aasmund Eldhuset



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!