0

I'm having some issues converting FileInputStream and FileOutputStream into CipherInputStream and CipherOutputStream for my 3DES encryption algorithm. Could someone direct me on the right path on how to do it? I end up getting the error: "CipherInputStream cannot be resolved to a type". Sorry if this is obvious.

// author Alexander Matheakis
public static void main(String[] args) throws Exception {


    // file to be encrypted
    FileInputStream inputFile = new FileInputStream("plainfile.txt");

    // encrypted file
    FileOutputStream outputFile = new FileOutputStream("C:\\Users\\islan\\OneDrive\\Documents\\Encryptor\\plainfile.des");

    // password to encrypt the file
    String passKey = "tkfhkggovubm";


    byte[] salt = new byte[8];
    SecureRandom r = new SecureRandom();    
    r.nextBytes(salt);
    PBEKeySpec pbeKeySpec = new PBEKeySpec(passKey.toCharArray());
    SecretKeyFactory secretKeyFactory = SecretKeyFactory
            .getInstance("PBEWithSHA1AndDESede");
    SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);


    PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 99999);
    Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede"); 
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParameterSpec);
    outputFile.write(salt);

    byte[] input = new byte[64];
    int bytesRead;
    while ((bytesRead = inputFile.read(input)) != -1) {
        byte[] output = cipher.update(input, 0, bytesRead);
        if (output != null)
            outputFile.write(output);
    }

    byte[] output = cipher.doFinal();
    if (output != null)
        outputFile.write(output);

    inputFile.close();
    outputFile.flush();
    outputFile.close();

// author Alexander Matheakis
adot710
  • 1
  • 1
  • You didn't provide your code for reading/CipherInputStream. Did you read away your salt before creating the CipherInputStream? – SirFartALot Apr 26 '19 at 13:30

1 Answers1

1

This works for me:

public class Cypher {

    // password to encrypt the file
    private static final String passKey = "tkfhkggovubm";

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

        try (FileInputStream inputFile = new FileInputStream("plainfile.txt");
                FileOutputStream outputFile = new FileOutputStream("plainfile.des");) {

            byte[] salt = new byte[8];
            SecureRandom r = new SecureRandom();
            r.nextBytes(salt);

            outputFile.write(salt);

            PBEKeySpec pbeKeySpec = new PBEKeySpec(passKey.toCharArray());
            SecretKeyFactory secretKeyFactory = SecretKeyFactory
                    .getInstance("PBEWithSHA1AndDESede");
            SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 99999);
            Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParameterSpec);

            try (CipherOutputStream cis = new CipherOutputStream(outputFile, cipher);) {
                IOUtils.copy(inputFile, cis);
            }
        }

        try (FileInputStream fis = new FileInputStream("plainfile.des");
                FileOutputStream outputFile = new FileOutputStream("plainfile.txt2");) {
            byte[] salt = new byte[8];
            int saltBytes = fis.read(salt);
            if (saltBytes!=salt.length)
                throw new Exception("Huh???");

            PBEKeySpec pbeKeySpec = new PBEKeySpec(passKey.toCharArray());
            SecretKeyFactory secretKeyFactory = SecretKeyFactory
                    .getInstance("PBEWithSHA1AndDESede");
            SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 99999);
            Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, pbeParameterSpec);

            try (CipherInputStream cis = new CipherInputStream(fis, cipher);) {
                IOUtils.copy(cis, outputFile);
            }
        }
    }
}

After executing the main, the plainfile.txt and the plainfile.txt2 are equal. The plainfile.des is crypted.

IOUtils.copy is a method in apache.commons-io, which internally reserves a buffer and writes all bytes from one stream to another. It's just the byte[] input = ... extracted into a method, plus using try-with-resources. This keeps the code simple and better readable.

SirFartALot
  • 1,215
  • 5
  • 25
  • Thanks @SirFartALot . Could I ask why you got rid of `byte[] input = new byte[64]; int bytesRead; while ((bytesRead = inputFile.read(input)) != -1)` for the encryption method? Does `try (CipherOutputStream cis = new CipherOutputStream(outputFile, cipher);) { IOUtils.copy(inputFile, cis);` do the same thing? – adot710 Apr 28 '19 at 18:06
  • @adot710: see answer. – SirFartALot Apr 29 '19 at 07:01