// 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
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);
}
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.
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();
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();
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();
}
}