Link to home
Start Free TrialLog in
Avatar of spectrumsofttech
spectrumsofttechFlag for India

asked on

File Encryption and Decryption

How to encrypt and decrypt file in java  using RSA (public key,private key)and AES algorithms.I want to upload encrypted file to server and clients can  download this file in decrypted format.
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Why not upload with https ? - it would be encrypted automatically. The receiving end would receive plaintext, but then that end can decrypt it anyway (by the sounds of things)
Avatar of spectrumsofttech

ASKER

In my application I want to encrypt file before upload to cloud , I used AES algorithm for file encryption and RSA for  encrypting AES Symmetric key .but I got an Error.
javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
      at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
      at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
      at javax.crypto.Cipher.doFinal(DashoA13*..)
      at EncryptionDecryption.EncryptionUtil.encrypt(EncryptionUtil.java:87)
      at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:144)
java.lang.IllegalArgumentException: Null input buffer
      at javax.crypto.Cipher.doFinal(DashoA13*..)
      at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:102)
      at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:149)
java.lang.NullPointerException
      at java.lang.String.<init>(String.java:593)
      at EncryptionDecryption.EncryptionUtil.decrypt(EncryptionUtil.java:108)
      at EncryptionDecryption.EncryptionUtil.main(EncryptionUtil.java:149)
You'll need to post your code
package EncryptionDecryption;
import java.io.BufferedInputStream;

public class EncryptionUtil {

  public static final String ALGORITHM = "RSA";

   public static final String PRIVATE_KEY_FILE = "private.txt";

  public static final String PUBLIC_KEY_FILE = "public.txt";

  public static void generateKey() {
    try {
      final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
      keyGen.initialize(1024);
      final KeyPair key = keyGen.generateKeyPair();

      File privateKeyFile = new File(PRIVATE_KEY_FILE);
      File publicKeyFile = new File(PUBLIC_KEY_FILE);

      // Create files to store public and private key
      if (privateKeyFile.getParentFile() != null) {
        privateKeyFile.getParentFile().mkdirs();
      }
      privateKeyFile.createNewFile();

      if (publicKeyFile.getParentFile() != null) {
        publicKeyFile.getParentFile().mkdirs();
      }
      publicKeyFile.createNewFile();

      // Saving the Public key in a file
      ObjectOutputStream publicKeyOS = new ObjectOutputStream(
          new FileOutputStream(publicKeyFile));
      publicKeyOS.writeObject(key.getPublic());
      System.out.println("public"+key.getPublic().getEncoded());
      publicKeyOS.close();

      // Saving the Private key in a file
      ObjectOutputStream privateKeyOS = new ObjectOutputStream(
          new FileOutputStream(privateKeyFile));
      privateKeyOS.writeObject(key.getPrivate());
      System.out.println("private"+key.getPrivate().getEncoded());
      //System.out.println(key.getPrivate());
      privateKeyOS.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

  }

  public static boolean areKeysPresent() {

    File privateKey = new File(PRIVATE_KEY_FILE);
    File publicKey = new File(PUBLIC_KEY_FILE);

    if (privateKey.exists() && publicKey.exists()) {
      return true;
    }
    return false;
  }

  public static byte[] encrypt(byte[]bs, PublicKey key) {
    byte[] cipherText = null;
    try {
      // get an RSA cipher object and print the provider
      final Cipher cipher = Cipher.getInstance(ALGORITHM);
      // encrypt the plain text using the public key
      cipher.init(Cipher.ENCRYPT_MODE, key);
      cipherText = cipher.doFinal(bs);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return cipherText;
  }

  public static String decrypt(byte[] text, PrivateKey key) {
    byte[] dectyptedText = null;
    try {
      // get an RSA cipher object and print the provider
      final Cipher cipher = Cipher.getInstance(ALGORITHM);

      // decrypt the text using the private key
      cipher.init(Cipher.DECRYPT_MODE, key);
      dectyptedText = cipher.doFinal(text);

    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return new String(dectyptedText);
  }

  public static void main(String[] args)throws IOException {
	 
	 
    try {
   	
        generateKey();
        File f=new File("test.txt"); //file is to encrypt
        byte[] contents = new byte[(int)f.length()];
        BufferedInputStream bis = null;
        try
        {
            bis = new BufferedInputStream(new FileInputStream(f));
            DataInputStream dis = new DataInputStream(bis);
            dis.readFully(contents);
        }
        finally
        {
            if(bis != null)
            {
                bis.close();
            }
        }           
        

     // final String originalText = "Text to be encrypted";
     

      // Encrypt the string using the public key
      ObjectInputStream  inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
      final PublicKey publicKey = (PublicKey) inputStream.readObject();
      final byte[] cipherText = encrypt(contents, publicKey);
      inputStream.close();
      // Decrypt the cipher text using the private key.
      ObjectInputStream inputStream1 = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
      final PrivateKey privateKey = (PrivateKey) inputStream1.readObject();
      final String plainText = decrypt(cipherText, privateKey);
      
      // Printing the Original, Encrypted and Decrypted Text
     
      System.out.println("Original Text: " + contents.toString());
      System.out.println("Encrypted Text: " +cipherText);
      System.out.println("Decrypted Text: " + plainText);
      inputStream.close();
      inputStream1.close();
      
    } catch (Exception e) {
      e.printStackTrace();
    }
    finally
    {
    	
    }
    
    }
  }

Open in new window

I have genrated public and private key using RSA algorithm.I want To store these key values in database. how to to store these values. I have used this code. for key generation
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
     SecureRandom random = new SecureRandom();
     pairgen.initialize(KEYSIZE, random);
     KeyPair keyPair = pairgen.generateKeyPair();
    byte[] publickey=keyPair.getPublic().getEncoded();
 
    //byte[] privatekey=keyPair.getPrivate().getEncoded();
That's not the code you're running (it wouldn't compile)

Please use code tags when posting code
ASKER CERTIFIED SOLUTION
Avatar of mccarl
mccarl
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I want to send encrypted key to client via email for  file decryption .But this is a 64 length byte array.How to send these byte array? Is any way to convert these byte array into small length String and convert to back.
Generally you would use a base64 encoding for this. There are a number of libraries available for doing this and also a number of ways in standard JDK but the one that I generally use is...

http://docs.oracle.com/javaee/6/api/javax/xml/bind/DatatypeConverter.html

Look in particular at the static "parseBase64Binary" and "printBase64Binary" methods for converting between byte[] and their String representations.
I want to send encrypted key to client via email for  file decryption .
Why would you send a method for securing data by an insecure method?
In my application the user can upload file to cloud in encrypted form.after uploading file the user send key to the data access member for file decryption when they downloading that file.The key Distribution is via Email..
It would probably be marginally safer to send the key through the post. Suffice it to say, it's not secure at all.
What you should be doing is encrypting the file with the public key of the intended recipient where possible.
@CEHJ,

spectrum could be a little bit more explicit in how he is wording the issue, but what he is doing is fine. He said that he wants to send the "encrypted" key via email. This is ok because this is the RSA public key encrypted version of the randomly generated AES key, ie. only the valid recipient who holds the correct private key can decrypt this key sent via email and make any use of it, decrypting the actual file.

What you should be doing is encrypting the file with the public key
This is the heart of the problem that we were dealing with above. You CAN'T directly encrypt the file using RSA public key encryption, as you are limited by the length of the input, ie. 117 bytes is not a lot, the file is likely to be much longer than that.
This is ok because this is the RSA public key encrypted version of the randomly generated AES key,
My apologies - i thought we'd somehow moved into discussing symmetric cryp only

You CAN'T directly encrypt the file using RSA public key encryption, as you are limited by the length of the input, ie. 117 bytes is not a lot, the file is likely to be much longer than that.
Not sure why you say that. There's no limit on the size of the plaintext. An example of RSA PKI:

http://javadigest.wordpress.com/2012/08/26/rsa-encryption-example/
Not sure why you say that. There's no limit on the size of the plaintext.
You might want to double check that ;)

Actually, funny you picked that example as it is the basis for the OP's code posted above. I'm assuming that you ran the code and confirmed that it runs as intended. However, note the input plaintext defined on this line towards the end of the example...
final String originalText = "Text to be encrypted ";

Open in new window

It's obviously much less than 117 bytes long. Now just copy & paste the string content at least 6 or so more times so that it IS long than 117 bytes and run the code again. Basically the same exceptions as the posted result at the top of this thread.
You might want to double check that ;)
OK, i've done that and it would seem that there is a natural limit. This could be circumvented by careful choice of the read buffer size and padding but afaik it's not really good practice to do this