I am trying to encrypt/decrypt using AES-GCM and JDK 1.8 CipherOutputStream, But getting BadPaddingException during decryption. I am using same IV and secret key during encryption and decryption, but not sure what is going wrong. Please see the code below:
static String AES_GCM_MODE = "AES/GCM/NoPadding";
SecretKey secretKey;
public SymmetricFileEncryption(){
Security.insertProviderAt( new BouncyCastleProvider(), 1);
setSecretKey();
}
public static void main(String[] args) throws Exception {
File inputFile = new File("test.txt");
File outputFile = new File("test-crypt.txt");
File out = new File("test-decrypt.txt");
SymmetricFileEncryption sym = new SymmetricFileEncryption();
sym.encrypt(inputFile, outputFile);
sym.decrypt(outputFile, out);
}
public Cipher getEncryptionCipher() throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException {
Cipher cipher = Cipher.getInstance(AES_GCM_MODE, "BC");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, getInitializationVector());
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(), new IvParameterSpec(getInitializationVector()) );
return cipher;
}
private Cipher getDecryptionCipher(File inputFile) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, IOException, NoSuchProviderException {
//initialize cipher
Cipher cipher = Cipher.getInstance(AES_GCM_MODE, "BC");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, getInitializationVector());
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(),new IvParameterSpec(getInitializationVector()) );
return cipher;
}
public void encrypt(File inputFile, File outputFile) throws Exception {
Cipher cipher = getEncryptionCipher();
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[16];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
}
cos.flush();
}catch (Exception e){
e.printStackTrace();
}
finally {
fos.close();
cos.close();
fis.close();
}
String iv = new String(cipher.getIV());
}
public void decrypt(File inputFile, File outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, NoSuchProviderException {
Cipher cipher = getDecryptionCipher(inputFile);
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
CipherInputStream cipherInputStream = null;
try{
inputStream = new FileInputStream(inputFile);
cipherInputStream = new CipherInputStream(inputStream, cipher);
outputStream = new FileOutputStream(outputFile);
byte[] data = new byte[16];
int read = cipherInputStream.read(data);
while(read != -1){
outputStream.write(data);
read = cipherInputStream.read(data);
}
outputStream.flush();
}catch (Exception e){
e.printStackTrace();
}
finally {
cipherInputStream.close();
inputStream.close();
outputStream.close();
}
}
public void setSecretKey(){
SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[16];
secureRandom.nextBytes(key);
secretKey = new SecretKeySpec(key, "AES");
}
public SecretKey getSecretKey(){
return secretKey;
}
public byte[] getInitializationVector(){
String ivstr = "1234567890ab"; //12 bytes
byte[] iv = ivstr.getBytes();//new byte[12];
return iv;
}
Above code results in following error during decryption at line
int read = cipherInputStream.read(data);
javax.crypto.BadPaddingException: mac check in GCM failed
at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:128)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:246)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:222)
at com.rocketsoftware.abr.encryption.SymmetricFileEncryption.decrypt(SymmetricFileEncryption.java:107)
Encryption doesn't work properly: In encrypt, CipherOutputStream#close must be called before FileOutputStream#close. This is because CipherOutputStream#close calls Cipher#doFinal that generates the tag and appends it to the ciphertext. This portion can only be written to the FileOutputStream-instance if FileOutputStream#close has not yet been called. By the way, CipherOutputStream#flush doesn't need to be called.
There is also a problem with decryption: In decrypt, outputStream.write(data) must be replaced by outputStream.write(data, 0, read). Otherwise usually too much data will be written to the FileOutputStream-instance.
The classes javax.crypto.CipherInputStream and javax.crypto.CipherOutputStream may perform the authentication false positive and are therefore not suitable for GCM-mode, e.g. from the documentation (Java 12) for CipherInputStream:
This class may catch BadPaddingException and other exceptions thrown by failed integrity checks during decryption. These exceptions are not re-thrown, so the client may not be informed that integrity checks failed. Because of this behavior, this class may not be suitable for use with decryption in an authenticated mode of operation (e.g. GCM). Applications that require authenticated encryption can use the Cipher API directly as an alternative to using this class.
Therefore, either the Cipher API should be used directly, as recommended in the documentation, or the BouncyCastle-implementations org.bouncycastle.crypto.io.CipherInputStream and org.bouncycastle.crypto.io.CipherOutputStream, e.g. for encryption:
import org.bouncycastle.crypto.io.CipherInputStream;
import org.bouncycastle.crypto.io.CipherOutputStream;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
...
public void encrypt(File inputFile, File outputFile) throws Exception {
AEADBlockCipher cipher = getEncryptionCipher();
// Following code as before (but with fixes described above)
...
}
public AEADBlockCipher getEncryptionCipher() throws Exception {
AEADBlockCipher cipher = new GCMBlockCipher(new AESEngine());
cipher.init(true, // encryption
new AEADParameters(
new KeyParameter(getSecretKey().getEncoded()),
128, // tag length
getInitializationVector(),
"Optional Associated Data".getBytes()));
return cipher;
}
...
and analog for decryption.
Note that even if authentication fails, decryption is performed, so the developer must ensure that the result is discarded and not used in this case.
Related
how to modify this AES encryption code so that it can encrypt and decrypt any type of file (pdf, docx....), because when I decrypt a pdf file or other I don't get the original file.
public EncryptData(File originalFile, File encrypted, SecretKeySpec secretKey, String cipherAlgorithm) throws IOException, GeneralSecurityException{
this.cipher = Cipher.getInstance(cipherAlgorithm);
encryptFile(getFileInBytes(originalFile), encrypted, secretKey);
}
public void encryptFile(byte[] input, File output, SecretKeySpec key) throws IOException, GeneralSecurityException {
this.cipher.init(Cipher.ENCRYPT_MODE, key);
writeToFile(output, this.cipher.doFinal(input));
}
public SecretKeySpec getSecretKey(String filename, String algorithm) throws IOException{
byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
return new SecretKeySpec(keyBytes, algorithm);
}
public static void main(String[] args) throws IOException, GeneralSecurityException, Exception{
StartEncryption startEnc = new StartEncryption();
File originalFile = new File("file.docx");
File encryptedFile = new File("EncryptedFiles/encryptedFile");
new EncryptData(originalFile, encryptedFile, startEnc.getSecretKey("OneKey/secretKey", "AES"), "AES");
}
public DecryptData(File encryptedFileReceived, File decryptedFile, SecretKeySpec secretKey, String algorithm) throws IOException, GeneralSecurityException {
this.cipher = Cipher.getInstance(algorithm);
decryptFile(getFileInBytes(encryptedFileReceived), decryptedFile, secretKey);
}
public void decryptFile(byte[] input, File output, SecretKeySpec key) throws IOException, GeneralSecurityException {
this.cipher.init(Cipher.DECRYPT_MODE, key);
writeToFile(output, this.cipher.doFinal(input));
}
public SecretKeySpec getSecretKey(String filename, String algorithm) throws IOException{
byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
return new SecretKeySpec(keyBytes, algorithm);
}
public static void main(String[] args) throws IOException, GeneralSecurityException, Exception{
StartDecryption startEnc = new StartDecryption();
File encryptedFileReceived = new File("EncryptedFiles/encryptedFile");
File decryptedFile = new File("DecryptedFiles/decryptedFile");
new DecryptData(encryptedFileReceived, decryptedFile, startEnc.getSecretKey("DecryptedFiles/SecretKey", "AES"), "AES");
}
As some important information regarding your source code is missing (method writeToFile, no information about the cipherAlgorithm, no information about the used key) your code is not executable.
Therefore I'm providing a sample program to encrypt and decrypt any kind of files using the AES mode ECB.
Security warning: do NOT use AES ECB Mode in production because it is UNSECURE ! It's better to use a mode like AES GCM.
Provide the filenames for the original file (plaintextfile), the encrypted file (ciphertextfile) and the decrypted file (decryptedfile) and
run the program - the decrypted file is equal to the original file.
I'm using a static key (32 byte/256 bit key length) for this example - to run this program you need the unlimited crypto policies enabled on your Java system.
That's the result:
https://stackoverflow.com/questions/62883618/encryption-decryption-aes-for-all-type-of-file-in-java
AES ECB Stream Encryption
* * * WARNING Do NOT use AES ECB mode in production as it is UNSECURE ! * * *
file used for encryption: plaintext.pdf
created encrypted file : plaintext.enc
created decrypted file : plaintext_decrypted.pdf
AES ECB Stream Encryption ended
The code:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class AES_ECB_Stream {
public static void main(String[] args) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
System.out.println("https://stackoverflow.com/questions/62883618/encryption-decryption-aes-for-all-type-of-file-in-java");
System.out.println("AES ECB Stream Encryption");
System.out.println("* * * WARNING Do NOT use AES ECB mode in production as it is UNSECURE ! * * *");
String plaintextFilename = "plaintext.pdf";
String ciphertextFilename = "plaintext.enc";
String decryptedtextFilename = "plaintext_decrypted.pdf";
byte[] key = "12345678901234561234567890123456".getBytes("UTF-8"); // 32 byte = 256 bit key length
encryptWitEcb(plaintextFilename, ciphertextFilename, key);
decryptWithEcb(ciphertextFilename, decryptedtextFilename, key);
System.out.println("file used for encryption: " + plaintextFilename);
System.out.println("created encrypted file : " + ciphertextFilename);
System.out.println("created decrypted file : " + decryptedtextFilename);
System.out.println("AES ECB Stream Encryption ended");
}
public static void encryptWitEcb(String filenamePlain, String filenameEnc, byte[] key) throws IOException,
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
try (FileInputStream fis = new FileInputStream(filenamePlain);
BufferedInputStream in = new BufferedInputStream(fis);
FileOutputStream out = new FileOutputStream(filenameEnc);
BufferedOutputStream bos = new BufferedOutputStream(out)) {
byte[] ibuf = new byte[1024];
int len;
while ((len = in.read(ibuf)) != -1) {
byte[] obuf = cipher.update(ibuf, 0, len);
if (obuf != null)
bos.write(obuf);
}
byte[] obuf = cipher.doFinal();
if (obuf != null)
bos.write(obuf);
}
}
public static void decryptWithEcb(String filenameEnc, String filenameDec, byte[] key) throws IOException,
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
try (FileInputStream in = new FileInputStream(filenameEnc);
FileOutputStream out = new FileOutputStream(filenameDec)) {
byte[] ibuf = new byte[1024];
int len;
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
while ((len = in.read(ibuf)) != -1) {
byte[] obuf = cipher.update(ibuf, 0, len);
if (obuf != null)
out.write(obuf);
}
byte[] obuf = cipher.doFinal();
if (obuf != null)
out.write(obuf);
}
}
}
This question already has answers here:
invalid AES key length error
(4 answers)
Closed 3 years ago.
I want to build App for encrypting and decrypting in java, but shows errors, how can I fix it?
I use AES algorithm for Encrypting and I use java, how can I fix it this code?
This is my code at CryptoException.java
public class CryptoException extends Exception {
public CryptoException() {}
public CryptoException(String message, Throwable throwable) {
super(message, throwable);
}
}
This is My code at CryptoUtils.java
public class CryptoUtils {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
public static void encrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static void decrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static void doCrypto(int cipherMode, String key, File inputFile, File outputFile) throws CryptoException {
try {
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException ex) {
throw new CryptoException("Error Encrypting/Decrypting file", ex);
}
}
}
And This is my MainApp.java
public class App {
public static void main( String[] args ) {
String key = "Rahasialah";
File inputFile = new File("D:\\document.txt");
File encryptedFile = new File("D:\\document.encrypted");
File decryptedFile = new File("D:\\document.decrypted");
try {
CryptoUtils.encrypt(key, inputFile, encryptedFile);
CryptoUtils.decrypt(key, encryptedFile, decryptedFile);
} catch (CryptoException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
}
This is my Messages Error:
Error Encrypting/Decrypting file
com.fusi24.bms.EncryptdanDecrypt.CryptoException: Error
Encrypting/Decrypting file
at com.fusi24.bms.EncryptdanDecrypt.CryptoUtils.doCrypto(CryptoUtils.java:53)
at com.fusi24.bms.EncryptdanDecrypt.CryptoUtils.encrypt(CryptoUtils.java:23)
at com.fusi24.bms.EncryptdanDecrypt.App.main(App.java:20)
Caused by: java.security.InvalidKeyException: Invalid AES key length: 10 bytes
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)
at com.sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.java:94)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:591)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:467)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:313)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:863)
at javax.crypto.Cipher.init(Cipher.java:1248)
at javax.crypto.Cipher.init(Cipher.java:1185)
at com.fusi24.bms.EncryptdanDecrypt.CryptoUtils.doCrypto(CryptoUtils.java:36)
... 2 more
You have to use AES encryption in the following way.
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // AES key size in number of bits
SecretKey secKey = generator.generateKey();
The size should be minimum 128 bits as mentioned above.
Then you have to use the following code to encrypt.
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
byte[] byteCipherText = aesCipher.doFinal(someTxtToEncrypt.getBytes());
I am using this below (E.1) for my application, there is obviously a huge glaring security hole in this that I recognize and understand. I have grown interested in encryption and want to understand it better, I need to generate a random key along with an IV but am unsure how to do so properly Can someone explain to me whom is familiar with AES encryption how this works (IV & KEY) So I am better able to understand in the future and can apply my knowledge, essentially I just want to make the code more secure, thank you.
(E.1)
byte[] key = "mykey".getBytes("UTF-8");
private byte[] getKeyBytes(final byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
return keyBytes;
}
public Cipher getCipherEncrypt(final byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public void encrypt(File in, File output, byte[] key) throws Exception {
Cipher cipher = getCipherEncrypt(key);
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(in);
fos = new FileOutputStream(output);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[1024];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
cos.flush();
} finally {
System.out.println("performed encrypt method now closing streams:\n" + output.toString());
cos.close();
fos.close();
fis.close();
}
}
public void watchMeEncrypt(){
encrypt(file, new File ("example.txt),key);
An AES key simply consists of random bytes. For CBC mode the IV mode should also be randomized (at least to an attacker). So in general you can simply use a SecureRandom instance to create the key and IV. The IV can then be included with the ciphertext; usually it is simply put in front of it.
With Java it is better to use a KeyGenerator though. If you look at the implementation of it in the SUN provider it will probably amount to the same thing. However using a KeyGenerator is more compatible with various kinds of keys and providers. It may well be that it is a requirement for generating keys in e.g. smart cards and HSM's.
So lets show a class with three simple methods:
package nl.owlstead.stackoverflow;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.util.Optional;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class CreateKeyAndIVForAES_CBC {
public static SecretKey createKey(final String algorithm, final int keysize, final Optional<Provider> provider, final Optional<SecureRandom> rng) throws NoSuchAlgorithmException {
final KeyGenerator keyGenerator;
if (provider.isPresent()) {
keyGenerator = KeyGenerator.getInstance(algorithm, provider.get());
} else {
keyGenerator = KeyGenerator.getInstance(algorithm);
}
if (rng.isPresent()) {
keyGenerator.init(keysize, rng.get());
} else {
// not really needed for the Sun provider which handles null OK
keyGenerator.init(keysize);
}
return keyGenerator.generateKey();
}
public static IvParameterSpec createIV(final int ivSizeBytes, final Optional<SecureRandom> rng) {
final byte[] iv = new byte[ivSizeBytes];
final SecureRandom theRNG = rng.orElse(new SecureRandom());
theRNG.nextBytes(iv);
return new IvParameterSpec(iv);
}
public static IvParameterSpec readIV(final int ivSizeBytes, final InputStream is) throws IOException {
final byte[] iv = new byte[ivSizeBytes];
int offset = 0;
while (offset < ivSizeBytes) {
final int read = is.read(iv, offset, ivSizeBytes - offset);
if (read == -1) {
throw new IOException("Too few bytes for IV in input stream");
}
offset += read;
}
return new IvParameterSpec(iv);
}
public static void main(String[] args) throws Exception {
final SecureRandom rng = new SecureRandom();
// you somehow need to distribute this key
final SecretKey aesKey = createKey("AES", 128, Optional.empty(), Optional.of(rng));
final byte[] plaintext = "owlstead".getBytes(UTF_8);
final byte[] ciphertext;
{
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec ivForCBC = createIV(aesCBC.getBlockSize(), Optional.of(rng));
aesCBC.init(Cipher.ENCRYPT_MODE, aesKey, ivForCBC);
baos.write(ivForCBC.getIV());
try (final CipherOutputStream cos = new CipherOutputStream(baos, aesCBC)) {
cos.write(plaintext);
}
ciphertext = baos.toByteArray();
}
final byte[] decrypted;
{
final ByteArrayInputStream bais = new ByteArrayInputStream(ciphertext);
final Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec ivForCBC = readIV(aesCBC.getBlockSize(), bais);
aesCBC.init(Cipher.DECRYPT_MODE, aesKey, ivForCBC);
final byte[] buf = new byte[1_024];
try (final CipherInputStream cis = new CipherInputStream(bais, aesCBC);
final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int read;
while ((read = cis.read(buf)) != -1) {
baos.write(buf, 0, read);
}
decrypted = baos.toByteArray();
}
}
System.out.println(new String(decrypted, UTF_8));
}
}
Note that you may not always want to generate and distribute an AES key "out-of-band". Here are a few other methods of generating a key (part #2 onwards). You may also want to take a look at more advanced exception handling for the cryptographic operation.
Ok guys ! There is my trouble.
I want to read data from an encrypted file and store the decrypted data in a local variable (without save it in a file).
So, when I do the operations (in the same Class) cryptingFile -> DecryptFile -> Storage : It's OK.
But, when I try to run again the code using the crypted file directly, I've got the error "BadPaddingException".
I've no idea what's going on....
Below, the working code:
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
generateKey(clef);
CryptingWithSave(Cipher.ENCRYPT_MODE,"db/db.csv",publicKey,"db/db.csv_encrypted");
decrypt_file("db/db.csv_encrypted",publicKey);
System.out.println(tab);
}
public static void generateKey (String clef) throws NoSuchAlgorithmException{
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
final SecretKey key = keyGen.generateKey();
publicKey= new SecretKeySpec(key.getEncoded(),"AES");
}
public static void CryptingWithSave (int Crypting_METHOD,String inputFile, SecretKeySpec clef, String outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, Exception{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Crypting_METHOD, clef);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
}
public static void decrypt_file (String inputFile, SecretKeySpec clef) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException{
Cipher cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, clef);
FileInputStream fis = new FileInputStream(inputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher2.update(input, 0, bytesRead);
if (output != null)
tab=tab.concat(new String(output));
}
byte[] output = cipher2.doFinal();
if (output != null)
tab=tab.concat(new String(output));
fis.close();
}
There, the unworking code (the only change is the CryptingWithSave which is commented):
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
generateKey(clef);
//CryptingWithSave(Cipher.ENCRYPT_MODE,"db/db.csv",publicKey,"db/db.csv_encrypted");
decrypt_file("db/db.csv_encrypted",publicKey);
System.out.println(tab);
}
public static void generateKey (String clef) throws NoSuchAlgorithmException{
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
final SecretKey key = keyGen.generateKey();
publicKey= new SecretKeySpec(key.getEncoded(),"AES");
}
public static void CryptingWithSave (int Crypting_METHOD,String inputFile, SecretKeySpec clef, String outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, Exception{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Crypting_METHOD, clef);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
}
public static void decrypt_file (String inputFile, SecretKeySpec clef) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException{
Cipher cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, clef);
FileInputStream fis = new FileInputStream(inputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher2.update(input, 0, bytesRead);
if (output != null)
tab=tab.concat(new String(output));
}
byte[] output = cipher2.doFinal();
if (output != null)
tab=tab.concat(new String(output));
fis.close();
}
It is because the next time you run it, it generates a new key which is different from the previous one. Try to use that old key.
O want to encrypt and decrypt files using my Java program.
These files are compiled Java .class files, I don't know what I am doing wrong. I am just testing now, but after encrypt and decrypt with the same key. It shows that file is
Exception in thread "AWT-EventQueue-0" java.lang.ClassFormatError: Truncated class file
and that class cannot be loaded.
There is my encrypter/decrypter class code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class EncTool {
public static void encrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("SomeFile.class");
OutputStream os = new FileOutputStream("SomeFile.class");
encrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("SomeFile.class");
OutputStream os = new FileOutputStream("SomeFile.class");
decrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
}
public static void decrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
}
and for testing im executing it that way:
try {
EncTool.encrypt("somekey123", "SomeFile");
EncTool.decrypt("somekey123", "SomeFile");
} catch (Throwable e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
What am i doing wrong?
Or maybe how should it be done?
EDIT
when my code looks that:
public static void encrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("Somefile.class");
OutputStream os = new FileOutputStream("tempfile.class");
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
File file2 = new File("tempfile.class");
File f = new File("somefile.class");
f.delete();
file2.renameTo(f);
}
Now it works, but these deleting and renaming thing doesn't look elegant, how can I do it more efficient?
You must write the output to a new file instead of overwriting the input while you are reading it. The way your code is written now the results will be undefined.