I am having a problem decrypting a file using RSA public key decryption. My process is to receive the xml file, encrypt the content, and write it back to the same file. Another function decrypts the content. My source code is:
public void decryptFile(String fileName,PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
FileInputStream fis = new FileInputStream(fileName);
File file=new File("decryptedfile.xml");
if(file.exists()) {
file.delete();
}
FileOutputStream fos = new FileOutputStream("decryptedfile.xml");
CipherInputStream cis = new CipherInputStream(fis, cipher);
int i;
byte[] block = new byte[32];
//System.out.println("Read : "+cis.read(block));
while ((i = cis.read(block)) != -1) {
System.out.println(String.valueOf(i));
fos.write(block, 0, i);
}
fos.close();
}
I just pass in the name of the encrypted file, and the corresponding private key value, into the function. However the cis.read(block) returns -1 on the first attempt. Can anyone suggest how I can decrypt the encrypted file?
Your file is almost certainly not RSA encrypted. Its probably encrypted with AES under a random symmetric key and the key is then encrypted with RSA.
You are assuming someone actually encrypted the entire file using just RSA. Assuming the implementation even lets you do this (i've seen ones that throw exceptions when one tries this), it would be way way way too slow to do anything useful.
Related
I am working on a program that I will use to encrypt and decrypt files using the JCE. My encryption and decryption is working correctly in default mode (ECB/PKCS5PADDING) however when I try to use CBC and I decrypt my file I am getting some of the text being junk (or when I try an image it gets corrupted.
Can anyone see what I am doing wrong? (I have not included my imports, can add if necessary)
public class encwork {
private static String keyString = "ykHySDZCWr16TVku"; //Encryption key
private static void bulkWork(int cipherMode, File inputFile, File outputFile) throws Exception{
//Let the user enter the key they wish to use
Key secretKey = new SecretKeySpec(keyString.getBytes(), "AES"); //Generates a key based on the default keysize for the specified algorithm
//Generate an Initialization Vector (IV)
final int ALG_KEYLENGTH = 128; //Change this as desired for the security level you want
byte[] iv = new byte[ALG_KEYLENGTH / 8]; //Save the IV bytes or send it in plaintext with the encrypted data so you can decrypt the data later
SecureRandom prng = new SecureRandom(); //Use SecureRandom to generate random bits. The size of the IV matches the blocksize of the cipher
prng.nextBytes(iv); //Construct the appropriate IvParameterSpec object for the data to pass to Cipher's init() method
//Create a Cipher by specifying the following parameters: Alg name, Mode (CBC), Padding (PKC7/PKCS5)
Cipher cipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5PADDING"); // Must specify the mode explicitly as most JCE providers default to ECB mode
//Initialize the Cipher for Encryption
cipherForEncryption.init(cipherMode, secretKey, new IvParameterSpec(iv));
//Declare / Initialize the Data, Convert the Input to Bytes and encrypt or decrypt using doFinal.
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipherForEncryption.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
}
public static void main(String[] args) {
File inputFile = new File("C:/Users/admin/Desktop/Crypto/In/test.txt");
File encryptedFile = new File("C:/Users/admin/Desktop/Crypto/Enc/test.encrypted");
File decryptedFile = new File("C:/Users/admin/Desktop/Crypto/Dec/testdec.txt");
//Encryption
try {
encwork.encrypt(inputFile, encryptedFile); //Encrypt method
} catch (Exception e) {
e.printStackTrace(); //Will show what caused the error in the console if an error occurs
}
//Decryption
try {
encwork.decrypt(encryptedFile, decryptedFile); //Decrypt method
} catch (Exception e) {
e.printStackTrace(); //Will show what caused the error in the console if an error occurs
}
}
public static void encrypt(File inputFile, File outputFile) throws Exception {
bulkWork(Cipher.ENCRYPT_MODE, inputFile, outputFile); //ENC_MODE = Constant used to initialize cipher to encryption mode.
}
public static void decrypt(File inputFile, File outputFile) throws Exception {
bulkWork(Cipher.DECRYPT_MODE, inputFile, outputFile); //ENC_MODE = Constant used to initialize cipher to encryption mode.
}}
You are not using the same IV for both encryption and decryption.
From the comment that the decryption starts: "the first line is "çQßs}# L¤qMä]this is a test" that would mean the IV for encryption and decryption is not the same.
This comment says it all:
//Save the IV bytes or send it in plaintext with the encrypted data so you can decrypt the data later
Either:
save the IV by returning it from the encryption and passing it in on decryption
or
prefix the encrypted data with the IV and on decryption split it off to use for decryption. (The IV does not need to be secret)
More on the IV and CBC mode, see Cipher Block Chaining (CBC):
While the IV influences the entire encrypted data CBC mode is self correcting and this means only the first block is incorrect when the wrong IV is used on decryption.
I am using AES symmetric encryption algorithm in java and after i encrypt file i want to put something on it to tell me it is encrypted so i can check for it is exist or not before decrypt it ?
Here is a sample of the code
` cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
jTextField3.setText(""+secretKeySpec);
String cleartextFile = "E:\\"+dir;
FileInputStream fis = new FileInputStream(cleartextFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream("E:\\d"+dir);
FileChannel out = fos.getChannel();
out.transferFrom(Channels.newChannel(cis), 0, Long.MAX_VALUE); `
I'm doing this project for a client and the part i'm currently stuck on involves taking a XML String and encrypting it - this doesn't need to be state of the art, it just needs to encrypt it and decrypt it using a password.
So far the user enters a password which i've hashed using SHA-256, I then try and encrypt it by doing this:
public static String encryptString(String password, String source, String fileName, String fileDir) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, FileNotFoundException, IOException {
FileOutputStream fos = null;
CipherInputStream cis;
byte key[] = password.getBytes();
SecretKeySpec secretKey = new SecretKeySpec(key, "DES");
Cipher encrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");
encrypt.init(Cipher.ENCRYPT_MODE, secretKey);
InputStream fileInputStream = new ByteArrayInputStream(source.getBytes());//Here I am getting file data as byte array. You can convert your file data to InputStream by other way too.
File dataFile = new File(fileDir, fileName); //dataDir is location where my file is stored
if (!dataFile.exists()) {
cis = new CipherInputStream(fileInputStream, encrypt);
try {
fos = new FileOutputStream(dataFile);
byte[] b = new byte[32];
int i;
while ((i = cis.read(b)) != -1) {
fos.write(b, 0, i);
}
return fileName;
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
cis.close();
fileInputStream.close();
} catch (IOException e) {
//IOException
}
}
}
return "";
}
The password being passed in is the hashed password - from here I try and run it but I get a:
java.security.InvalidKeyException: Invalid key length: 64 bytes exception.
Can someone help please?
Or tell me of a better way to encrypt an XML file with a password?
Thanks
From the docs.
If this cipher requires any algorithm parameters that cannot be
derived from the given key, the underlying cipher implementation is
supposed to generate the required parameters itself (using
provider-specific default or random values) if it is being initialized
for encryption or key wrapping, and raise an InvalidKeyException if it
is being initialized for decryption or key unwrapping. The generated
parameters can be retrieved using getParameters or getIV (if the
parameter is an IV).
A very simple way of encrypting is taking your hash and XOR it with the bytes in the file in a loop (256 bits at a time). It's kind of a low-level approach but you won't need to debug the API. You should be able to implement this with very minimal code.
So I have these large files (6GB+) that I need to decrypt on a 32 bit computer. The general procedure that I used previously was to read the entire file in memory, then pass it on to the decrypt function and then write it all back to a file. This doesn't really work due to memory limitations. I did try passing the file in parts to the decrypt function but it seems to mess up around the boundaries of where I break up the file before sending it to the decrypt function.
I've tried breaking up the file in parts relative to key size but that doesnt seem to matter. I tried a byte array of size 2048 as well as a byte aray of size 294 thinking that might be the special boundary but, no luck. I can see parts of the file correctly decrypted but parts which are total gibberish.
Is it just NOT POSSIBLE to decrypt the file in chunks? If there is a way, then how?
Here is my decryption function / my attempt to decrypt in parts.
private Path outFile;
private void decryptFile(FileInputStream fis, byte[] initVector, byte[] aesKey, long used) {
//Assume used = 0 for this function.
byte[] chunks = new byte[2048]; //If this number is greater than or equal to the size of the file then we are good.
try {
if (outFile.toFile().exists())
outFile.toFile().delete();
outFile.toFile().createNewFile();
FileOutputStream fos = new FileOutputStream(outFile.toFile());
OutputStreamWriter out = new OutputStreamWriter(fos);
IvParameterSpec spec = new IvParameterSpec(Arrays.copyOfRange(initVector, 0, 16));
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, spec);
int x;
while ((x = fis.read(chunks, 0, chunks.length)) != -1) {
byte[] dec = cipher.doFinal(Arrays.copyOfRange(chunks, 0, x));
out.append(new String(dec));
}
out.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
LOG.error(ExceptionUtils.getStackTrace(e));
}
}
Consider using Cipher#update(byte[], int, int, byte[], int) instead of doFinal() for multipart operations. This will take care of part boundaries for you.
The last part of the deciphered data can be obtained by calling the doFinal(byte[] output, int outputOffset) method.
I have been doing web programming for several years now and since then I have not done any programming for desktop applications, and I have forgotten so many things. Please be patient if this is too simple.
Now I have this situation:
I am trying to store some hashed words in a file. I think I should use binary files for this (please correct me if I am wrong). But I have no idea how should I write the words to the file. I tried many ways, but when I read back the file, and try to decrypt the words, I get BadPaddingException.
Does anyone have any idea how to write the words to a file?
P.S: I use this code for encrypting/decrypting the words (I got it from another StackOverflow thread, with a few modifications):
public static byte[] encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt, 20));
return pbeCipher.doFinal(property.getBytes("UTF-8"));
}
public static String decrypt(byte[] property) throws GeneralSecurityException, IOException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(salt, 20));
return new String(pbeCipher.doFinal(property));
}
Well, just use FileInputStream and FileOutputStream =)
Sample writing:
// encrypted data in array
byte[] data = ...
FileOutputStream fos = ...
fos.write(data, 0, data.length);
fos.flush();
fos.close();
Sample reading:
File inputFile = new File(filePath);
byte[] data = new byte[inputFile.length()];
FileInputStream fis = new FileInputStream(inputFile);
fis.read(data, 0, data.length);
fis.close();
Above code assumes that one file holds single encrypted item. If you need to hold more than one item in the single file, you'll need to devise some format scheme for that. For example, you can store number of bytes in encrypted data as 2 bytes, before data itself. 2 bytes per item means encrypted item can not be longer than 2^16 bytes. Of course, you can use 4 bytes for length.
Saving as a text document would seem to make more sense to me, the data is already a so there's no need to convert it to a byte[] and if you need to read from the file would be pretty convenient. Unless you're saving it from the web and its already coming through a socket as a byte[]. I know it says don't provide your opinion but its strictly a matter of opinion, that was the only part of your question left unanswered by the previous two answered