Encrypt Deflate and encode to Base64 Xml - java

// XML needs to encrypt and deflate and encode using BASE64?I've used this code for this but I am not getting the exact output.
public String encryptDeflateAndBase64(String decryptedString) throws IOException {
byte[] b=decryptedString.getBytes("UTF-8");
byte[] c = new byte[550];
Deflater compresser=new Deflater();
compresser.setInput(b);
compresser.finish();
System.out.println(compresser.deflate(c));
compresser.end();
/*ByteArrayOutputStream bos = new ByteArrayOutputStream(decryptedString.length());
byte[] buf = new byte[4096];
while (!compresser.finished()) {
int count = compresser.deflate(buf);
bos.write(buf, 0, count);
}
bos.close();
byte[] compressedData = bos.toByteArray();
*/ byte[] output = Base64.encodeBase64(c);
return new String(output);
}

//Remove: System.out.println(compresser.deflate(c));
int count = compresser.deflate(c);
ByteBuffer bb = ByteBuffer.wrap(c, 0, count);
byte[] output = Base64.getEncoder().encode(bb);
Where I used the java.util.Base64. To not copy bytes, I used a ByteBuffer.

Related

How to compress and decompress byte array with zstd algorithm in java

I'm trying to use ZSTD algorithm to compress and decompress byte array.
I read the ZSTD document that will give more details about implementation, but I can't still implement sufficient method to compress and decompress byte arrays.
If anyone can explain to me what I have to do it would be appreciated.
public static byte[] compressZstd(byte[] input) throws IOException {
var compressor = new ZstdCompressor();
byte[] compressedBuffer = new byte[1024];
compressor.compress(input, 0, input.length, compressedBuffer, 0, 1024);
return compressedBuffer;
}
public static byte[] decompressZstd(byte[] input) throws IOException {
var decompressor = new ZstdDecompressor();
byte[] decompressedBuffer = new byte[1024];
decompressor.decompress(input, 0, input.length, decompressedBuffer, 0, 1024);
return decompressedBuffer;
}
You should determine the size of the buffer and also determine the index value of the buffer.
public static byte[] compressZstd(byte[] input) throws IOException {
var compressor = new ZstdCompressor();
int maxCompressLength = compressor.maxCompressedLength(input.length);
byte[] compressedBuffer = new byte[maxCompressLength];
int compressedSize = compressor.compress(input, 0, input.length, compressedBuffer, 0, compressedBuffer.length);
return Arrays.copyOfRange(compressedBuffer, 0, compressedSize);
}
public static byte[] decompressZstd(byte[] compressed) throws IOException {
var decompressor = new ZstdDecompressor();
byte[] decompressedBuffer = new byte[Integer.MAX_VALUE];
int decompressedSize = decompressor
.decompress(compressed, 0, compressed.length, decompressedBuffer, 0, decompressedBuffer.length);
return Arrays.copyOfRange(decompressedBuffer, 0, decompressedSize);
}

Android GZIP decompress breaks unicode characters at buffer limits

I decompress received GZIPped data to string. Problem when I have BUFFER_SIZE as 512 it breaks unicode characters at buffer limit points. As a result I get text with question marks. It happens with non latin letters.
...во и ��ргуме...
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 512;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}
The error is in the algorithm, assuming that the block being read ends (and starts) on a UTF-8 bytes sequence border.
So do it as follows:
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((bytesRead = gis.read(data)) != -1) {
baos.write(data, 0, bytesRead);
}
gis.close();
is.close();
return baos.toString("UTF-8");
You can wrap the GZIPInputStream into an InputStreamReader and read characters instead of bytes. By doing so, you don't have the problem of potentially invalid encodings at the buffer boundaries.

How to properly split a file into byte arrays in Android

I have a file that I intend to send over the network, so I tried to split it into byte arrays:
File myFile = new File(selectedImagePath);
byte[] fileByteArray = new byte[(int) myFile.length()];
Log.i("MyApp", " File byte size: " + fileByteArray.length);
List<byte[]> listOfBytes = new ArrayList<byte[]>();
int pos = 0;
while (pos < fileByteArray.length)
{
int length = pos + size > fileByteArray.length ? fileByteArray.length - pos : size;
byte[] act_byte = new byte[length];
Log.i("MyApp","Length: "+length);
System.arraycopy(fileByteArray, pos, act_byte, 0, length);
pos += length;
listOfBytes.add(act_byte);
}
List<byte[]> sending=new ArrayList<byte[]>();
for(byte[] ba:listOfBytes)
{
byte[] arr = new byte[ba.length + 2];
arr[0] = new Integer(W).byteValue();
arr[1] = new Integer(Z).byteValue();
System.arraycopy(ba, 0, arr, 2, ba.length);
sending.add(arr);
}
Let the file size be 10000 bytes.
On the receiving size, I get 10000 bytes, yet the file isn't readable.
byte[] message = new byte[size + 2];
DatagramPacket p = new DatagramPacket(message, message.length);
s = new DatagramSocket(SERVERPORT);
List<byte[]> incomingBA=new ArrayList<byte[]>();
while (true)
{
s.receive(p);
int a=new Byte(p.getData()[0]).intValue();
int b=new Byte(p.getData()[1]).intValue();
int actualSize = p.getLength();
byte[] actualBA=new byte[actualSize-2];
System.arraycopy(p.getData(),2,actualBA,0,actualBA.length);
incomingBA.add(actualBA);
if(X==22)
{
byte[] result=concatenateByteArrays(incomingBA);
FileOutputStream fos = new FileOutputStream("/mnt/sdcard/Download/X.jpg");
//BufferedOutputStream bos = new BufferedOutputStream(fos);
fos.write(result,0,result.length);
fos.flush();
fos.close();
incomingBA.clear();
}
public byte[] concatenateByteArrays(List<byte[]> blocks) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (byte[] b : blocks) {
os.write(b, 0, b.length);
}
return os.toByteArray();
}
What did I do wrong?
I forgot to read the content of the file into the byte array, so I needed to use this code:
FileInputStream fileInputStream = new FileInputStream(myFile);
fileInputStream.read(fileByteArray);
fileInputStream.close();

Decompressing a byte[] using GzipInputStream

I have a class that compresses and decompresses a byte array;
public class Compressor
{
public static byte[] compress(final byte[] input) throws IOException
{
try (ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gzipper = new GZIPOutputStream(bout))
{
gzipper.write(input, 0, input.length);
gzipper.close();
return bout.toByteArray();
}
}
public static byte[] decompress(final byte[] input) throws IOException
{
try (ByteArrayInputStream bin = new ByteArrayInputStream(input);
GZIPInputStream gzipper = new GZIPInputStream(bin))
{
// Not sure where to go here
}
}
}
How do I decompress the input and return a byte array?
Note: I don't want to do any conversion to strings because of character encoding issues.
your missing code will be something like
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len;
while ((len = gzipper.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
gzipper.close();
out.close();
return out.toByteArray();

BouncyCastle Last Byte Decrypt Problem

I am decrypting an XML file from the file system using Bouncy Castle. I output the decrypted text and get a fatal error SAXParseException on the very last byte of data. Below is my decryption method and the setup of the cipher object.
I was initially using cipher streams, and everything worked perfect (commented out code was my stream). Due to policy files and end users not having the 256 bit unlimited versions I need to use bouncy castle.
Any ideas why the final byte is not coming through?
From Constructor:
keyParam = new KeyParameter(key);
engine = new AESEngine();
paddedBufferedBlockCipher =
new PaddedBufferedBlockCipher(new CBCBlockCipher(engine));
Decrypt Method:
public void decrypt(InputStream in, OutputStream out) {
try
{
paddedBufferedBlockCipher.init(false,
new ParametersWithIV(keyParam, _defaultIv));
// cipher.init(Cipher.DECRYPT_MODE, secretKey, ivs);
// CipherInputStream cipherInputStream
// = new CipherInputStream(in, cipher);
byte[] buffer = new byte[4096];
byte[] outBuffer = new byte[4096];
for (int count = 0; (count = in.read(buffer)) != -1;) {
paddedBufferedBlockCipher.processBytes(buffer, 0,
count, outBuffer, 0);
out.write(outBuffer, 0, count);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
[Fatal Error] :40:23: Element type "Publi" must be followed by either attribute specifications, ">" or "/>".
org.xml.sax.SAXParseException: Element type "Publi" must be followed by either attribute specifications, ">" or "/>".
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:264)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:292)
Do you call doFinal() with the final chunk of data?
public void decrypt(InputStream in, OutputStream out) {
try
{
paddedBufferedBlockCipher.init(false,
new ParametersWithIV(keyParam, _defaultIv));
byte[] buffer = new byte[4096];
byte[] outBuffer = new byte[4096];
for (int count = 0; (count = in.read(buffer)) != -1;) {
int c2 = paddedBufferedBlockCipher.processBytes(buffer, 0,
count, outBuffer, 0);
out.write(outBuffer, 0, c2);
}
count = paddedBufferedBlockCipher.doFinal(outBuffer, 0);
out.write(outBuffer, 0, count);
}
catch(Exception e) {
e.printStackTrace();
}
}

Categories