Accname
2D-Graphics enthusiast
- Reaction score
- 1,462
Hi there.
I was having a crazy idea recently. I was thinking how safe it would be to share files with each other over the internet by using the PNG-file format for encryption.
If I take a piece of music, or a video, or software, or anything; and, instead of uploading it somewhere as is, I encrypt it and transform it into an image, then upload it as an image to some image hosting service.
Somebody else can then download this image easily, run it through a decryption program, and have it restored 1 to 1.
There are several benefits to this. First of all you can upload any file type to a simple image hosting service. You can easily split the file into different parts with imaging software and somebody else can just put them back together.
Its hard to decrypt the file without knowing what kind of file it originally was.
You can also add a generated random key for extra protection.
And, file size is reduced by using the standard PNG compression methods.
I have actually already written an encryption algorithm which can turn any file into a png.
However, I have problems loading the file again. Maybe somebody here knows why, and this is why I am posting this.
The problem is that a few bytes will be returned as -1 although I am very sure I didnt put -1 in there.
Here is my encryption code:
This works very well so far.
Now here is the code for loading the image and converting it back:
These are some example outputs I got:
I would guess this has to do with the way PNG's are stored, but I am not 100% sure.
By the way, without the png compression I get the very same results. The encoders and decoders work flawlessly. I already tested these.
Thank you a bunch.
I was having a crazy idea recently. I was thinking how safe it would be to share files with each other over the internet by using the PNG-file format for encryption.
If I take a piece of music, or a video, or software, or anything; and, instead of uploading it somewhere as is, I encrypt it and transform it into an image, then upload it as an image to some image hosting service.
Somebody else can then download this image easily, run it through a decryption program, and have it restored 1 to 1.
There are several benefits to this. First of all you can upload any file type to a simple image hosting service. You can easily split the file into different parts with imaging software and somebody else can just put them back together.
Its hard to decrypt the file without knowing what kind of file it originally was.
You can also add a generated random key for extra protection.
And, file size is reduced by using the standard PNG compression methods.
I have actually already written an encryption algorithm which can turn any file into a png.
However, I have problems loading the file again. Maybe somebody here knows why, and this is why I am posting this.
The problem is that a few bytes will be returned as -1 although I am very sure I didnt put -1 in there.
Here is my encryption code:
Code:
public static void encrypt(File file) throws IOException {
/*
* Read the file byte by byte and store the information in a list.
*/
DataInputStream is = new DataInputStream(new FileInputStream(file));
ArrayList<Byte> data = new ArrayList<>();
try {
while (true) {
data.add(is.readByte());
}
} catch (EOFException eof) {
}
is.close();
/*
* Calculations for various important variables.
*/
int sizeInBytes = data.size();
System.out.println("Size in bytes "+sizeInBytes);
int sizeInPixels = sizeInBytes / BYTES_PER_PIXEL;
System.out.println("Size in pixels "+sizeInPixels);
int imgWidth = (int) Math.ceil(Math.sqrt(sizeInPixels + 4));
System.out.println("Image width "+imgWidth);
int imgHeight = (int) Math.ceil((sizeInPixels + 4) * 1f / imgWidth);
System.out.println("Image height "+imgHeight);
int imgTotalPixels = imgWidth * imgHeight;
System.out.println("Image total pixels "+imgTotalPixels);
int imgTotalBytes = imgTotalPixels * BYTES_PER_PIXEL;
System.out.println("Image total bytes "+imgTotalBytes);
/*
* Create buffer to store
*/
byte[] pixels = new byte[imgTotalBytes];
// Store the size of the file in the first 4 bytes:
pixels[0] = (byte) (sizeInBytes >> 0);
pixels[1] = (byte) (sizeInBytes >> 8);
pixels[2] = (byte) (sizeInBytes >> 16);
pixels[3] = (byte) (sizeInBytes >> 24);
// Store the rest of the file as is:
for (int i = 0; i < data.size(); i++) {
if (i % 4 == 0) {
System.out.println();
}
if (pixels[i] >= 0) {
System.out.print(' ');
}
if (pixels[i] / 100 == 0) {
System.out.print(' ');
}
if (pixels[i] / 10 == 0) {
System.out.print(' ');
}
System.out.print(pixels[i]);
System.out.print(", ");
pixels[4 + i] = data.get(i);
}
/*
* Save the file as a compressed png.
*/
PNGEncoder.save(file.getAbsolutePath()+".png", pixels, imgWidth, imgHeight, Filter.NONE, Compression.LEVEL_9);
System.out.println("finished");
}
Now here is the code for loading the image and converting it back:
Code:
public static void decrypt(File file) throws IOException {
/*
* Load the file and decode it.
*/
InputStream stream = new FileInputStream(file);
PNGDecoder decoder = new PNGDecoder(stream);
int width = decoder.getWidth();
int height = decoder.getHeight();
System.out.println("Image size "+width+" x "+height);
ByteBuffer buffer = ByteBuffer.allocate(width * height * 4).order(ByteOrder.LITTLE_ENDIAN);
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
stream.close();
buffer.clear();
/*
* Load the size of the original file from the first 4 bytes.
*/
byte[] sizeInBytesArray = new byte[] {
buffer.get(),
buffer.get(),
buffer.get(),
buffer.get()
};
System.out.println("First 4 bytes "+sizeInBytesArray[0]+", "+sizeInBytesArray[1]+", "+sizeInBytesArray[2]+", "+sizeInBytesArray[3]);
int sizeInBytes = ((sizeInBytesArray[3] & 0xFF) << 24) | ((sizeInBytesArray[2] & 0xFF) << 16)
| ((sizeInBytesArray[1] & 0xFF) << 8) | (sizeInBytesArray[0] & 0xFF);
System.out.println("Size in bytes "+sizeInBytes);
System.out.println("Buffer.remaining = "+buffer.remaining());
/*
* Write the file to disk and output the contents.
*/
DataOutputStream out = new DataOutputStream(new FileOutputStream(file.getAbsolutePath()+".zip"));
for (int i = 0; i < sizeInBytes; i++) {
if (i % 4 == 0) {
System.out.println();
}
byte b = buffer.get();
if (b >= 0) {
System.out.print(' ');
}
if (b / 100 == 0) {
System.out.print(' ');
}
if (b / 10 == 0) {
System.out.print(' ');
}
System.out.print(b);
System.out.print(", ");
out.write(b);
}
out.close();
System.out.println("finished");
}
Encryption:
Decryption:
Code:
-118, 0, 0, 0,
80, 75, 3, 4,
20, 0, 2, 0,
8, 0, 102, -109,
116, 67, 30, -35,
77, 70, 14, 0,
0, 0, 34, 0,
0, 0, 13, 0,
0, 0, 84, 101,
115, 116, 45, 84,
101, 120, 116, 46,
116, 120, 116, 11,
73, 45, 46, 81,
40, 65, 33, -112,
-111, -98, -98, 30,
0, 80, 75, 1,
2, 20, 0, 20,
0, 2, 0, 8,
0, 102, -109, 116,
67, 30, -35, 77,
70, 14, 0, 0,
0, 34, 0, 0,
0, 13, 0, 0,
0, 0, 0, 0,
0, 1, 0, 32,
0, 0, 0, 0,
0, 0, 0, 84,
101, 115, 116, 45,
84, 101, 120, 116,
46, 116, 120, 116,
80, 75, 5, 6,
0, 0, 0, 0,
1, 0, 1, 0,
59, 0, 0, 0,
57, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
Decryption:
Code:
-118, 0, 0, -1,
-1, 80, 75, 3,
4, 20, 0, 2,
0, 8, 0, 102,
-109, 116, 67, 30,
-35, 77, 70, 14,
0, 0, 0, 34,
0, 0, 0, 13,
0, 0, 0, 84,
101, 115, 116, 45,
84, 101, 120, 116,
46, 116, 120, 116,
11, 73, 45, 46,
81, 40, 65, 33,
-112, -1, -1, -98,
-1, 0, 80, 75,
1, 2, 20, 0,
20, 0, 2, 0,
8, -1, -1, -109,
-1, -1, -1, -35,
-1, 70, 14, 0,
0, 0, 34, 0,
0, 0, 13, 0,
0, 0, 0, 0,
0, 0, 1, 0,
32, 0, 0, 0,
0, 0, 0, 0,
84, 101, 115, 116,
45, 84, 101, 120,
116, 46, 116, 120,
116, 80, 75, 5,
6, 0, 0, 0,
0, 1, 0, 1,
0, 59, 0, 0,
0, 57, 0, 0,
0, 0,
I would guess this has to do with the way PNG's are stored, but I am not 100% sure.
By the way, without the png compression I get the very same results. The encoders and decoders work flawlessly. I already tested these.
Thank you a bunch.