I am trying to build a Java program that compresses, then encrypts files using AES encryption. However, I am getting the following error during the encryption process:
Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider supporting PBKDF2WithHmacSHA256
at java.base/javax.crypto.Cipher.getInstance(Cipher.java:574)
at MyJavaProject.zip.encryptFile(zip.java:75)
at MyJavaProject.zip.main(zip.java:58)
I've included my code below. It's supposed to compress the file I point it toward, then encrypt it, and save the bytes for the salt and IV so I can decrypt later. I'm using Java 16 and my JRE is JavaSE-12.
class zip {
public static void main(String[] args) throws IOException, InvalidKeyException, NoSuchPaddingException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException, BadPaddingException,
IllegalBlockSizeException, InvalidKeySpecException {
FileInputStream fis = new FileInputStream("texty.txt");
FileOutputStream fos = new FileOutputStream("texty(comp)");
DeflaterOutputStream dos = new DeflaterOutputStream(fos);
int data;
while ((data = fis.read()) != -1) {
dos.write(data);
}
fis.close();
dos.close();
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
SecretKey key = getKeyFromPassword("Password", salt.toString());
String algorithm = "AES/CBC/PKCS5Padding";
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
IvParameterSpec Iv = new IvParameterSpec(iv);
encryptFile(algorithm, key, Iv, new File("texty(comp)"), new File("texty(compNenc)"));
FileOutputStream fs = new FileOutputStream(new File("intravenus"));
BufferedOutputStream bos = new BufferedOutputStream(fs);
bos.write(iv);
bos.close();
FileOutputStream fs2 = new FileOutputStream(new File("pepper"));
BufferedOutputStream bos2 = new BufferedOutputStream(fs2);
bos2.write(salt);
bos2.close();
}
public static void encryptFile(String algorithm, SecretKey key, IvParameterSpec iv, File inputFile, File outputFile)
throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
inputStream.close();
outputStream.close();
}
public static SecretKey getKeyFromPassword(String password, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
}
UPDATE:
Thanks you to #that other guy for helping me out with the initial error, but now I have a new one that I am not quite advanced enough to understand. When I try and download the bytes I store for the salt and IV, and attempt to decrypt the file, I get the following error message:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2091)
at MyJavaProject.unzip.decryptFile(unzip.java:99)
at MyJavaProject.unzip.main(unzip.java:52)
My code for the decryption file is listed below. If anyone could help I'd greatly appreciate it.
class unzip {
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
NoSuchPaddingException, InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException {
byte[] fileData = new byte[16];
DataInputStream dis = null;
dis = new DataInputStream(new FileInputStream(new File("intravenus")));
dis.readFully(fileData);
if (dis != null) {
dis.close();
}
byte[] iv = fileData;
IvParameterSpec Iv = new IvParameterSpec(iv);
byte[] fileData2 = new byte[16];
DataInputStream dis2 = null;
dis2 = new DataInputStream(new FileInputStream(new File("pepper")));
dis2.readFully(fileData2);
if (dis2 != null) {
dis2.close();
}
byte[] salt = fileData2;
SecretKey key = getKeyFromPassword("Password", salt.toString());
String algorithm = "AES/CBC/PKCS5Padding";
decryptFile(algorithm, key, Iv, new File("texty(compNenc)"), new File("texty(compNdec)"));
// assign Input File : file2 to FileInputStream for reading data
FileInputStream fis = new FileInputStream("texty(compNdec)");
// assign output file: file3 to FileOutputStream for reading the data
FileOutputStream fos = new FileOutputStream("texty(decompNdec)");
// assign inflaterInputStream to FileInputStream for uncompressing the data
InflaterInputStream iis = new InflaterInputStream(fis);
// read data from inflaterInputStream and write it into FileOutputStream
int data;
while ((data = iis.read()) != -1) {
fos.write(data);
}
// close the files
fos.close();
iis.close();
}
public static SecretKey getKeyFromPassword(String password, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return secret;
}
public static void decryptFile(String algorithm, SecretKey key, IvParameterSpec iv, File encryptedFile,
File decryptedFile) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
FileInputStream inputStream = new FileInputStream(encryptedFile);
FileOutputStream outputStream = new FileOutputStream(decryptedFile);
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] output = cipher.doFinal();
if (output != null) {
outputStream.write(output);
}
inputStream.close();
outputStream.close();
}
}
Related
Im trying to write a program to encrypt any type of file. I had my encryption classes already done, when I noticed (at first it worked) that I am getting an AEADBadTagException whenever I try to decrypt any of my files.
Here is my encryption/decryption class:
class Encryptor {
private static final String algorithm = "AES/GCM/NoPadding";
private final int tagLengthBit = 128; // must be one of {128, 120, 112, 104, 96}
private final int ivLengthByte = 12;
private final int saltLengthByte = 64;
protected final Charset UTF_8 = StandardCharsets.UTF_8;
private CryptoUtils crypto = new CryptoUtils();
// return a base64 encoded AES encrypted text
/**
*
* #param pText to encrypt
* #param password password for encryption
* #return encoded pText
* #throws Exception
*/
protected byte[] encrypt(byte[] pText, char[] password) throws Exception {
// 64 bytes salt
byte[] salt = crypto.getRandomNonce(saltLengthByte);
// GCM recommended 12 bytes iv?
byte[] iv = crypto.getRandomNonce(ivLengthByte);
// secret key from password
SecretKey aesKeyFromPassword = crypto.getAESKeyFromPassword(password, salt);
Cipher cipher = Cipher.getInstance(algorithm);
// ASE-GCM needs GCMParameterSpec
cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv));
byte[] cipherText = cipher.doFinal(pText);
// prefix IV and Salt to cipher text
byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length).put(iv).put(salt)
.put(cipherText).array();
Main.clearArray(password, null);
Main.clearArray(null, salt);
Main.clearArray(null, iv);
Main.clearArray(null, cipherText);
aesKeyFromPassword = null;
cipher = null;
try {
return cipherTextWithIvSalt;
} finally {
Main.clearArray(null, cipherTextWithIvSalt);
}
}
// für Files
protected byte[] decrypt(byte[] encryptedText, char[] password)
throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
// get back the iv and salt from the cipher text
ByteBuffer bb = ByteBuffer.wrap(encryptedText);
byte[] iv = new byte[ivLengthByte];
bb.get(iv);
byte[] salt = new byte[saltLengthByte];
bb.get(salt);
byte[] cipherText = new byte[bb.remaining()];
bb.get(cipherText);
// get back the aes key from the same password and salt
SecretKey aesKeyFromPassword;
aesKeyFromPassword = crypto.getAESKeyFromPassword(password, salt);
Cipher cipher;
cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv));
byte[] plainText = cipher.doFinal(cipherText);
Main.clearArray(password, null);
Main.clearArray(null, iv);
Main.clearArray(null, salt);
Main.clearArray(null, cipherText);
aesKeyFromPassword = null;
cipher = null;
bb = null;
try {
return plainText;
} finally {
Main.clearArray(null, plainText);
}
}
protected void encryptFile(String file, char[] pw) throws Exception {
Path pathToFile = Paths.get(file);
byte[] fileCont = Files.readAllBytes(pathToFile);
byte[] encrypted = encrypt(fileCont, pw);
Files.write(pathToFile, encrypted);
Main.clearArray(pw, null);
Main.clearArray(null, fileCont);
Main.clearArray(null, encrypted);
}
protected void decryptFile(String file, char[] pw)
throws IOException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
Path pathToFile = Paths.get(file);
byte[] fileCont = Files.readAllBytes(pathToFile);
byte[] decrypted = decrypt(fileCont, pw);
Files.write(pathToFile, decrypted);
Main.clearArray(pw, null);
Main.clearArray(null, fileCont);
Main.clearArray(null, decrypted);
}
}
The corresponding CryptoUtils class:
class CryptoUtils {
protected byte[] getRandomNonce(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
try {
return nonce;
} finally {
Main.clearArray(null, nonce);
}
}
// Password derived AES 256 bits secret key
protected SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
// iterationCount = 65536
// keyLength = 256
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
try {
return secret;
} finally {
secret = null;
}
}
// hex representation
protected String hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
try {
return result.toString();
} finally {
result.delete(0, result.length() - 1);
}
}
// print hex with block size split
protected String hexWithBlockSize(byte[] bytes, int blockSize) {
String hex = hex(bytes);
// one hex = 2 chars
blockSize = blockSize * 2;
// better idea how to print this?
List<String> result = new ArrayList<>();
int index = 0;
while (index < hex.length()) {
result.add(hex.substring(index, Math.min(index + blockSize, hex.length())));
index += blockSize;
}
try {
return result.toString();
} finally {
result.clear();
}
}
}
The Exception occurs at byte[] plainText = cipher.doFinal(cipherText); in the decrypt method.
Im unsure if the tagLenthBit must be the ivLengthByte * 8, I did try it though and it didnt make any difference.
I'm providing my own example code for AES 256 GCM file encryption with PBKDF2 key derivation because I'm too lazy to check all parts of your code :-)
The encryption is done with CipherInput-/Outputstreams because that avoids "out of memory errors" when encrypting larger files (your code is reading the complete plaintext / ciphertext in a byte array).
Please note that the code has no exception handling, no clearing of sensitive data/variables and the encryption/decryption result is a simple "file exist" routine but I'm sure you can use it as a good basis for your program.
That's a sample output:
AES 256 GCM-mode PBKDF2 with SHA512 key derivation file encryption
result encryption: true
result decryption: true
code:
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class AesGcmEncryptionInlineIvPbkdf2BufferedCipherInputStreamSoExample {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidKeySpecException, InvalidAlgorithmParameterException {
System.out.println("AES 256 GCM-mode PBKDF2 with SHA512 key derivation file encryption");
char[] password = "123456".toCharArray();
int iterations = 65536;
String uncryptedFilename = "uncrypted.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
boolean result;
result = encryptGcmFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, password, iterations);
System.out.println("result encryption: " + result);
result = decryptGcmFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, password, iterations);
System.out.println("result decryption: " + result);
}
public static boolean encryptGcmFileBufferedCipherOutputStream(String inputFilename, String outputFilename, char[] password, int iterations) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException {
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[32];
secureRandom.nextBytes(salt);
byte[] nonce = new byte[12];
secureRandom.nextBytes(nonce);
Cipher cipher = Cipher.getInstance("AES/GCM/NOPadding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(nonce);
out.write(salt);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keySpec = new PBEKeySpec(password, salt, iterations, 32 * 8); // 128 - 192 - 256
byte[] key = secretKeyFactory.generateSecret(keySpec).getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, nonce);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec);
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 decryptGcmFileBufferedCipherInputStream(String inputFilename, String outputFilename, char[] password, int iterations) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] salt = new byte[32];
byte[] nonce = new byte[12];
Cipher cipher = Cipher.getInstance("AES/GCM/NOPadding");
try (FileInputStream in = new FileInputStream(inputFilename); // i don't care about the path as all is lokal
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename)) // i don't care about the path as all is lokal
{
byte[] buffer = new byte[8192];
in.read(nonce);
in.read(salt);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keySpec = new PBEKeySpec(password, salt, iterations, 32 * 8); // 128 - 192 - 256
byte[] key = secretKeyFactory.generateSecret(keySpec).getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, nonce);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
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;
}
}
}
I am using socket to transfer file and AES 256 to encrypt/decrypt, I use the byte array to accept file's content and encrypt it, but only the first byte size array success to decrypt and other appeared garbled(the encrypted byte size extend to 1368 and AES block size is 128bits not sure is it effect),below is my code:
public void sendfile() {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) >= 0) {
String encryptString = new String(byteArray, "UTF-8");
bos.write(EncryptAES.encrypt(encryptString, "12345").getBytes("UTF-8"));
}
}
public void receiveFile(File file, BufferedInputStream bis) {
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = bis.read(byteArray)) >= 0) {
String encryptString = new String(byteArray, "UTF-8");
bos.write(EncryptAES.decrypt(encryptString, "12345").getBytes("UTF-8"));
}
}
public static String encrypt(String content,SecretKey secretKey) {
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] byteContent = cipher.doFinal(content.getBytes("UTF-8"));
return Base64.getEncoder().withoutPadding().encodeToString(byteContent);
}
public static String decrypt(String content,SecretKey secretKey) {
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] byteCipherText = Base64.getDecoder().decode(content);
String encryptString = new String(byteCipherText, "UTF-8");
byte[] decryptedText = cipher.doFinal(byteCipherText);
encryptString = new String(decryptedText, "UTF-8");
return new String(decryptedText, "UTF-8");
}
I am trying to decrypt a file in java. The first 16 bytes of decrypted file are IV (initialization vector). Please help in resolving the above exception.
I am trying to prepend the IV in the output file in AESFileEncryption() and then reading it while decryption.
Thank You.
public class AESFileEncryption {
public static void encrypt(String path,String pwd) throws Exception {
FileOutputStream outFile;
try (
FileInputStream inFile = new FileInputStream(path)) {
String fileName=path;
System.out.println(path);
outFile = new FileOutputStream(fileName+".aes");
// password to encrypt the file
String password = pwd;
byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(),salt,65536,128);// user-chosen password that can be used with password-based encryption (PBE).
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");//Secret KeySpec is a class and implements inteface SecretKey
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[16];
random.nextBytes(bytes);
IvParameterSpec ivspec = new IvParameterSpec(bytes);
cipher.init(Cipher.ENCRYPT_MODE, secret,ivspec);//opmode,key
outFile.write(bytes);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inFile.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
Files.write(Paths.get(fileName+".aes"), output, StandardOpenOption.APPEND);
} byte[] output = cipher.doFinal();
if (output != null)
Files.write(Paths.get(fileName+".aes"), output, StandardOpenOption.APPEND);
}
outFile.flush();
outFile.close();
File f=new File(path);
boolean x=f.delete();
if(x){
System.out.println("File deleted");
}
JOptionPane.showMessageDialog(null,"File Encrypted.");
}
}
Decryption code
public class AESFileDecryption {
public static void decrypt(String path,String pwd) throws Exception {
String password = pwd;
String fileName=path;
File file=new File(path);
//System.out.println(inFile.toString());
String fileNameWithOutExt = path.replaceFirst("[.][^.]+$", "");
System.out.println(fileName);
System.out.println(fileNameWithOutExt);
byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
System.out.println("1");
FileInputStream fis = new FileInputStream(path);
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(),salt,65536,128);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
System.out.println("2");
// file decryption
Cipher cipher=null;
byte bytes[]=new byte[16];
fis.read(bytes, 0, 16);
IvParameterSpec ivspec = new IvParameterSpec(bytes);
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
System.out.println("3");
FileOutputStream fos = new FileOutputStream(fileNameWithOutExt);
System.out.println("4");
byte[] in = new byte[64];
int read;
while ((read = fis.read(in,16,(int)file.length()-16)) != -1) {
byte[] output = cipher.update(in, 0, read);
if (output != null)
fos.write(output);
}
try{
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
System.out.println("File Decrypted.");
}
catch(IOException | BadPaddingException | IllegalBlockSizeException e)
{
System.out.println(e+"");
}
}
}
There are a few problems with the small example, but the one that is most immediately your problem is the line
while ((read = fis.read(in,16,(int)file.length()-16)) != -1) {
You seem to be confused about the meaning of the offset parameter to the read(). It is not the offset into the file, but rather the offset into the array (in) that is specified in the first parameter.
A non-exhaustive list of other problems that I see include:
writing to the file using the two independent mechanisms (FileOutputStream.write() and Files.write()). This actually worked ok when I ran your program but it seems like it's asking for trouble. There's no reason to use Files.write() here.
fis.read(bytes, 0, 16); does not check the return value.
It seems you are struggling with finding some IO idioms that you're comfortable with. Or perhaps just experimenting. At the risk of giving you even more options to juggle, you might consider investigating google's open source Guava library. Many people find it has just what they needed.
This question already has answers here:
java.security.InvalidKeyException: Illegal key size
(3 answers)
Closed 6 years ago.
i'm using free IAIK-JCE for my program. Here:
http://javadoc.iaik.tugraz.at/iaik_jce/current/iaik/security/cipher/MARS.html
it says that MARS can use keys from 128 do 448 ( with 32bits increments ). But when im trying to use key diffrent than 128b than i get:
Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
My code:
public void marsEncryption(Integer dlugoscKlucza, File file, List<User> listaOdbiorcow, ProgressBar pb,String mode) throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, NoSuchPaddingException, IOException,
IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
//Generowanie klucza
SecretKey secretKey = generateMarsSymetricKey(dlugoscKlucza);
//inicjalizacja
Cipher cipher = Cipher.getInstance("MARS/"+mode+"/PKCS5Padding", "IAIK");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
//Pobranie wektora poczatkowego
byte[] ivBytes = cipher.getIV();
IvParameterSpec iv = new IvParameterSpec(ivBytes);
//Zamiana klucza na tablice bajtow
byte[] KeyBytes = secretKey.getEncoded();
//Zaszyfrowanie klucza symetrycznego kluczem publicznym odbiorcow
for (User odbiorca : listaOdbiorcow) {
byte[] encryptedKey = rsaEncryption(KeyBytes, odbiorca.publicKey);
odbiorca.symetricKey = Base64.encodeBase64String(encryptedKey);
}
//Zapisanie do pliku xmla
XMLFactory.createXML(dlugoscKlucza, ivBytes, listaOdbiorcow, file.toString());
//Szyforwanie pliku
String newFile = file.toString() + "Crypt.xml";
encryptTask = new Task<Void>() {
#Override
protected Void call() throws Exception {
FileOutputStream fos = new FileOutputStream(newFile, true);
try (FileInputStream fis = new FileInputStream(file.toString())) {
byte[] block = new byte[(int) (128)];
double postep = 0;
double postepMax = file.length();
updateProgress(0, postepMax);
int i;
while ((i = fis.read(block)) != -1) {
//Szyfrowanie
byte[] block2 = cipher.update(block, 0, i);
//Zapisanie do pliku
postep += i;
updateProgress(postep, postepMax);
if (isCancelled()) {
fis.close();
fos.close();
File f = new File(newFile);
f.delete();
updateProgress(0, postepMax);
break;
}
fos.write(block2);
}
byte[] outputFinalUpdate = cipher.doFinal();
fos.write(outputFinalUpdate);
return null;
}
}
};
pb.progressProperty().bind(encryptTask.progressProperty());
new Thread(encryptTask).start();
}
private SecretKey generateMarsSymetricKey(int dlugoscKlucza) throws NoSuchAlgorithmException, NoSuchProviderException {
KeyGenerator keyGen = KeyGenerator.getInstance("MARS", "IAIK");
System.out.println("Wybrana długość klucza: " + dlugoscKlucza);
keyGen.init(dlugoscKlucza);
SecretKey secretKey = keyGen.generateKey();
return secretKey;
}
It fail on:
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
Can someone say what am i doing wrong?
I found solution. Maybe someone will have same problem in the future so i post solution: it should work with any Algorithm. You have to download JCE from:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
And override files in
\Java\jdk1.8.0_45\jre\lib\security
Im sending a file from Server to a Client but i need to send a encrypted file with AES 256 and receive a original for client use in diferente machine.
I want use 2 string to generate a SHA256 for example: "fruit" and "car29".
After generate this key I want to use this key as secretkey to encrypt with AES256.The client and server know the two strings.
My server code:
public final static int SOCKET_PORT = 4444;
public final static String FILE_TO_SEND = "C:\\file.txt";
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File(FILE_TO_SEND);
byte[] mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println("Done.");
} finally {
if (bis != null) {
bis.close();
}
if (os != null) {
os.close();
}
if (sock != null) {
sock.close();
}
}
}
} finally {
if (servsock != null) {
servsock.close();
}
}
}
My client code:
public final static int SOCKET_PORT = 4444;
public final static String SERVER = "127.0.0.1";
public final static String FILE_TO_RECEIVED = "C:\\file.txt";
public final static int FILE_SIZE = 6022386;
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
sock = new Socket(SERVER, SOCKET_PORT);
System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
}
}
Thanks in advance!
There's some function I write for you, check it out.
For generating HASH/Digest:
public byte[] generateHASH(byte[] message) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(message);
return hash;
}
For Encryption:
public byte[] encrypt(byte[] msg, byte[] key, byte[] iv) throws Exception {
//prepare key
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//prepare cipher
String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm
Cipher cipher = Cipher.getInstance(cipherALG);
String string = cipher.getAlgorithm();
//as iv (Initial Vector) is only required for CBC mode
if (string.contains("CBC")) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
}
byte[] encMessage = cipher.doFinal(msg);
return encMessage;
}
For Decryption:
public byte[] decrypt(byte[] encMsgtoDec, byte[] key, byte[] iv) throws Exception {
//prepare key
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//prepare cipher
String cipherALG = "AES/CBC/PKCS5padding"; // use your preferred algorithm
Cipher cipher = Cipher.getInstance(cipherALG);
String string = cipher.getAlgorithm();
//as iv (Initial Vector) is only required for CBC mode
if (string.contains("CBC")) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
}
byte[] decMsg = cipher.doFinal(encMsgtoDec);
return decMsg;
}
Note:
If you use CBC mode, then both encrypt() and decrypt() use same iv, otherwise you don't need iv, and of course key is same for both.
Your key generation process is naive. You better use RSA public key encryption for key exchange or Diffie–Hellman key exchange method for secret key transfer.
I would suggest you to use SSL. The data encryption comes by default. The SSL handshake takes care of generating and exchanging the encryption keys and subsequently encrypting the data from the source and decrypting it at the receiving end. All this happens at the transport layer and the application does not have to bother or do anything explicit except for configuring it to use SSL.