0

In the code below, I grab an existing pdf file, encrypt it and then output the encrypted file. My problem is that the outputted file does not work properly. It creates a file of zero bytes. I tried the same code with a simple text file "sample.txt" and it worked fine. The outputted file was created with encryption.

Can anyone tell me what I may be doing wrong? Does it work differently with PDF files?

public void encryptFile() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, CertificateException, KeyStoreException, IOException {

    FileInputStream fis = new FileInputStream("c:\\sample.pdf");
    FileOutputStream fos = new FileOutputStream("c:\\sample_encrypted");

    Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
    c.init(Cipher.ENCRYPT_MODE, getSapPublicCertificate().getPublicKey());
    CipherOutputStream cos = new CipherOutputStream(fos, c);

    byte[] buf = new byte[2048];
    int read;
    while ((read = fis.read(buf)) != -1) {
        cos.write(buf, 0, read);
    }

    fis.close();
    cos.flush();
    cos.close();
}

EDIT I should mention that I tried the same thing above but without any cipher/cipherOutPutStream and the new cloned file was generated properly. The code is below. So I would tend to believe its an issue with Cipher or CipherOutputStream. But then again, as mentioned before, it all worked fine with a simple text file.

    byte[] buffer = new byte[2048];
    int read;
    while ((read = fis.read(buffer)) != -1) {
        fos.write(buffer, 0, read);
    }

EDIT2 Content of method getCertficate()

public Certificate getSapPublicCertificate() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
    char[] password = "mypass".toCharArray();
    String alias = "myalias";

    FileInputStream fIn = new FileInputStream(keystoreSapCertificate);
    KeyStore keystore = KeyStore.getInstance("JKS");

    keystore.load(fIn, password);
    Certificate cert = keystore.getCertificate(alias);

    return cert;
}
LatinCanuck
  • 454
  • 2
  • 10
  • 29
  • Do you know what value does the getSapPublicCertificate().getPublicKey() returns ? – Jay Apr 25 '14 at 14:10
  • Hi Jay, I added the method definition above. My pair keys were generated using the info from this [link](https://blogs.oracle.com/java-platform-group/entry/self_signed_certificates_for_a) – LatinCanuck Apr 25 '14 at 14:29

1 Answers1

2

You need to use hybrid encryption. You cannot encrypt large files using RSA. I do wonder though how you handle your errors or what you do when your program doesn't finish; issues like these should be caught by the Java runtime system.

The file handling is not different between text files and PDF files, it's just the size that is different.


Hybrid encryption comes down to:

  1. Generate fully random symmetric key (e.g. AES-128);
  2. Encrypt the file, e.g. using AES-CBC with zero IV;
  3. Encrypt the symmetric key with RSA-OAEP or RSA-PKCS#1;
  4. Send or store the ciphertext and the encrypted symmetric key;

Decryption goes like this:

  1. Retrieve the ciphertext and the RSA encrypted symmetric key;
  2. Decrypt the symmetric key using the private key;
  3. Decrypt the ciphertext.
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Hi, Let me see if I understand this hybrid system and please correct me if I'm off. I need to encrypt the file using a symmetric algorithm. Then encrypt the symmetric key and the symmetrically encrypted file together using the public key. Then, I use the asymmetric private key to decrypt it all. This will give me the symmetric key and the encrypted file. I then use the symmetric key to decrypt the symmetrically encrypted file. Am I close? – LatinCanuck Apr 30 '14 at 18:43
  • Close indeed, I'll put it in the answer. – Maarten Bodewes May 01 '14 at 12:04