Java: How to write binary files? - java

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

Related

how to append a byte array to file without overwriting it using java

I trying to make an AES encryption and i am generating a salt . However i had encountered some issue. the below code work fine but whenever i encrypted the second and so on files, the salt in side the file is overwritten. any suggestion on how to append the salt byte [] into the salt fil without overwriting it ?
Guys..i updated my code..thanks for that portion although it fixed the overwritting issue, it does not make it to next line.
output on my file : ˜V"÷ҲÖ4ô¦ŒT‰mÊî0‘Z^'û•šÙK· = this is two salt combined.
any idea how to make it append on next line?
i trying saltoutfile.write("/n") but doesnt work
public byte[] generateSalt() throws IOException{
//generate Salt value
// password, iv and salt should be transferred to the other end
// in a secure manner
// salt is used for encoding
// writing it to a file
// salt should be transferred to the recipient securely
// for decryption
byte[] salt = new byte[8];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(salt);
FileOutputStream saltOutFile = new FileOutputStream("C:\\KryptZIP\\salt.enc" , true);
saltOutFile.write(salt);
saltOutFile.close();
return salt;
}
as mentioned in comment: this is my read salt value
public static byte[] readSalt() throws IOException{
// reading the salt
// user should have secure mechanism to transfer the
// salt, iv and password to the recipient
FileInputStream saltFis = new FileInputStream("C:\\KryptZIP\\salt.enc");
byte[] salt = new byte[8];
saltFis.read(salt);
saltFis.close();
return salt;
}
You need to use the constructor of FileOutputStream with 2 arguments. The second argument is a boolean flag indicating whether you want to append (true) to the file or write from the beginning (false).
Change your code to:
FileOutputStream saltOutFile = new FileOutputStream("C:\\KryptZIP\\salt.enc", true);
Use the Apache FileUtils. Use the methdod
FileUtils.writeByteArrayToFile(java.io.File file,bytes[] content,boolean append)

Java Decryption Returns Blank

I'm currently working on an encryption program, and I'm having an issue when decrypting. The resulting file is blank, and I have been trying to find the reason for this for about an hour. My decryption code is below...
Can someone please tell me why my data might come out blank?
file = x;
FileInputStream fis = new FileInputStream(file.getAbsolutePath());
file = new File(file.getAbsolutePath().substring(0,
file.getAbsolutePath().length() - 4));
FileOutputStream fos = new FileOutputStream(file);
byte k[] = Hash.MD5(password).getBytes("UTF-8");
SecretKeySpec key = new SecretKeySpec(k, "AES");
Cipher cipher = Cipher.getInstance(algorithm);
byte[] iv = batchIV;
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
CipherInputStream cin = new CipherInputStream(fis,
cipher);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = cin.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
fos.flush();
fos.close();
cin.close();
Links go to larger code portions.
Decrypt Method Here: http://pastebin.com/2p2juUTa
Full Class Here: http://pastebin.com/hgZHT4wg
I've found that the CipherInputStream is returning -1 when you try to read from it... I'm still unsure as to what might cause this, if anyone can help.
You don't state what Hash.MD5() and Hash.MD5R() do, let alone supply the source code, but evidently MD5() returns a String, which is already an error (see below), and that MD5R() only returns the input argument, which is basically pointless. Unless you think you've discovered a way to reverse MD5? You haven't.
If you make the following changes to your code:
change MD5() to return the byte[] resulting from the MessageDigest.digest() operation that it must perform, instead of wrapping that in a String, and make the corresponding adjustments at the callings sites (i.e. remove .toByteArray("UTF-8") in a couple of places, and
change MD5R() to return the input argument, or just remove the method,
you will find that your code works.
NB:
Repeat after me: 'String is not a container for binary data'.
flush() before close() is redundant.
The File variable file should be method-local, not static.
You don't need all those File.getAbsolutePath() method calls. getPath() will work just as well in most cases, or just the File object itself in others.

Encrypting a XML file in Java with a password

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.

Decrypt file in parts

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.

Decrypt the encrypted file content?

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.

Categories

Resources