I'm writing a encryption and decryption code as follows
import java.io.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.BadPaddingException;
import java.nio.file.Files;
import java.util.Scanner;
public class EncryptFile
{
public static void main(String args[]) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
//Encrypt Mode
FileOutputStream outputStream = new FileOutputStream(new File("D:\\encryptedNewStringFile.txt"));
Key secretKey = new SecretKeySpec("encKey".getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] getFileBytes = "writing a file using encryption ".getBytes();
byte[] outputBytes = cipher.doFinal(getFileBytes);
outputStream.write(outputBytes);
getFileBytes = "\n".getBytes();
outputBytes = cipher.doFinal(getFileBytes);
outputStream.write(outputBytes);
getFileBytes = "This is New Line 2 \nThis is NewLine 3".getBytes();
outputBytes = cipher.doFinal(getFileBytes);
outputStream.write(outputBytes);
outputStream.close();
//Decrypt Mode
File curFile = new File("D:\\encryptedNewStringFile.txt");
secretKey = new SecretKeySpec("encKey".getBytes(), "Blowfish");
cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
getFileBytes = Files.readAllBytes(curFile.toPath());
outputBytes = cipher.doFinal(getFileBytes);
InputStream bai = new ByteArrayInputStream(outputBytes);
BufferedReader bfReader = new BufferedReader(new InputStreamReader(bai));
Scanner scan = new Scanner(bfReader);
while(scan.hasNextLine())
{
System.out.println(scan.nextLine());
}
}
}
here i have a problem in output which is the printed output has some extra symbols (i.e question marks and box symbols)in it.
The output i received is
Any suggestions will be really helpful thanks in advance
Combining the answers from @Artjom B. and @The 5th column mouse you get a file encryption program that will encrypt a file with Blowfish in CBC mode. The encryption and decryption is done in chunks so large files (up to some GB) could get encrypted and decrypted without "out of memory errors".
The key is generated randomly, and you should keep in mind - without knowledge of the key no decryption of the file is possible.
output:
file encryption with Blowfish CBC mode
used key (Base64): jsErS04so1NCC7Jmds6Grr+0tPkNoaj0hx/izLaW5H8=
result encryption: true
result decryption: true
Security warning: the code has no exception handling, no correct file handling (e.g. overwriting without notice) and is for educational purpose only:
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class BlowfishCbcFileEncryption {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidAlgorithmParameterException {
System.out.println("file encryption with Blowfish CBC mode");
String uncryptedFilename = "uncrypted.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
// random blowfish 256 key
byte[] key = new byte[32];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(key);
System.out.println("used key (Base64): " + base64Encoding(key));
// random iv
byte[] iv = new byte[8]; // blowfish iv is 8 bytes long
secureRandom.nextBytes(iv);
boolean result;
result = encryptCbcFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, key, iv);
System.out.println("result encryption: " + result);
result = decryptCbcFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, key);
System.out.println("result decryption: " + result);
}
public static boolean encryptCbcFileBufferedCipherOutputStream(String inputFilename, String outputFilename, byte[] key, byte[] iv)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
public static boolean decryptCbcFileBufferedCipherInputStream(String inputFilename, String outputFilename, byte[] key) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] iv = new byte[8]; // blowfish iv is 8 bytes long
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFilename); // i don't care about the path as all is local
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename)) // i don't care about the path as all is local
{
byte[] buffer = new byte[8192];
in.read(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "Blowfish");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
private static String base64Encoding(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
}