JCPABE Encypt Decrypt String - java

I see the JCPABE project, but the methods that are in classes enable me to encrypt file or InputStream but not a simple Java string. How can I use these methods to encrypt/decrypt a string ? I have tried to convert the string in byte array but it doesn't work (i.e. String.getBytes("UTF_8"); same if i convert the String in an InputStream. How can I encrypt/decrypt a simple string?
Example:
My simple code:
String test="Message";
policy="newyork or losangeles";
Cpabe.encrypt(publickey, policy, test, test);
I have this message: The method encrypt(File, String, File, File) in the type Cpabe is not applicable for the arguments (File, String, String, String).
The function encrypt is this:
public static void encrypt(File publicKeyFile, String policy, File inputFile, File outputFile) throws IOException, AbeEncryptionException {
AbePublicKey publicKey = AbePublicKey.readFromFile(publicKeyFile);
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(inputFile));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile))) {
encrypt(publicKey, policy, in, out);
}
I have changed the function in:
public static void encrypt(File publicKeyFile, String policy, String inputstr, String outputstr) throws IOException, AbeEncryptionException {
AbePublicKey publicKey = AbePublicKey.readFromFile(publicKeyFile);
try (String in = new String(inputstr);
String out = new String(outputstr)) {
encrypt(publicKey, policy, in, out);
}
}
but I have other message: The resource type String does not implement java.lang.AutoCloseable on the String in and String out; while on the encrypt I have these message: The method encrypt(AbePublicKey, String, InputStream, OutputStream) in the type Cpabe is not applicable for the arguments (AbePublicKey, String, String, String).
This is the function with the 2 InputStream parameters:
public static void encrypt(AbePublicKey publicKey, String policy, InputStream input, OutputStream output) throws AbeEncryptionException, IOException {
AbeEncrypted encrypted = encrypt(publicKey, policy, input);
encrypted.writeEncryptedData(output, publicKey);
}
and this is the writeEncryptedData method:
public void writeEncryptedData(OutputStream out, AbePublicKey publicKey) throws IOException {
AbeOutputStream abeOut = new AbeOutputStream(out, publicKey);
Version.writeToStream(abeOut);
cipher.writeToStream(abeOut);
abeOut.writeInt(iv.length);
abeOut.write(iv);
byte[] buffer = new byte[1024];
int len;
while ((len = dataStream.read(buffer)) != -1) {
abeOut.write(buffer, 0, len);
}
}

Your code can not because of various reasons. First you need an InputStream and OutputStream. To use a String you have to first convert it to byte[] and then to a stream.
In your function you defined something like a "out parameter" String outputstr. However Strings are immutable in Java, therefore you can not use it that way and change it's content. Use it as return value instead.
Third never ever try to convert byte[] to String using new String(<byte array>). This does not return a String with printable characters but a String with binary non-printable content. You have to encode it e.g. using base64. Before decrypting it you have to apply base64 decode.
public static String encrypt(File publicKeyFile, String policy, String inputstr) throws IOException, AbeEncryptionException {
AbePublicKey publicKey = AbePublicKey.readFromFile(publicKeyFile);
try (InputStream in = new ByteArrayInputStream(inputstr.getBytes(StandardCharsets.UTF_8);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
encrypt(publicKey, policy, in, out);
return Base64.getEncoder().encodeToString(out.toByteArray());
}
}

Related

How to correctly encode and decode a string in Base64?

I want to encode a string in Base64 for later decoding it. I encode it doing this:
public static String encryptString(String string) {
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes());
return (new String(bytesEncoded));
}
Then, the encoded string is stored on disk using UTF-8. After restarting the application, the encoded string is readed from disk and I'm trying to decode the string using this:
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string);
return (new String(valueDecoded));
}
Something is wrong because it is giving me this exception:
java.lang.IllegalArgumentException: Illegal base64 character d
at java.base/java.util.Base64$Decoder.decode0(Base64.java:743)
at java.base/java.util.Base64$Decoder.decode(Base64.java:535)
at java.base/java.util.Base64$Decoder.decode(Base64.java:558)
This is a TRACE step by step
1º i encode this: {"configuration":{"shop":{"name":"","addressLine1":"","addressLine2":"","postalCode":"","city":"","country":"","phoneNumber":""}},"jointBets":[],"groups":[{"name":"Test","members":[]}]}
into this: eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IiIsImFkZHJlc3NMaW5lMSI6IiIsImFkZHJlc3NMaW5lMiI6IiIsInBvc3RhbENvZGUiOiIiLCJjaXR5IjoiIiwiY291bnRyeSI6IiIsInBob25lTnVtYmVyIjoiIn19LCJqb2ludEJldHMiOltdLCJncm91cHMiOlt7Im5hbWUiOiJUZXN0IiwibWVtYmVycyI6W119XX0=
2º i store it on disk in utf8
3º i retreive it from disk and it's this string:
eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IiIsImFkZHJlc3NMaW5lMSI6IiIsImFkZHJlc3NMaW5lMiI6IiIsInBvc3RhbENvZGUiOiIiLCJjaXR5IjoiIiwiY291bnRyeSI6IiIsInBob25lTnVtYmVyIjoiIn19LCJqb2ludEJldHMiOltdLCJncm91cHMiOlt7Im5hbWUiOiJUZXN0IiwibWVtYmVycyI6W119XX0=
4º i decode it and get the exception.
The old Base64 utility add linebreaks every 76 characters in Java8.
The result looks like that:
/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a
HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy
MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
...
It seems that this behaviour changed with some version. At least with Java11 the decoder is not accepting line-breaks anymore.
To avoid the problem you could change you method
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string.replace("\n","").replace("\r","");
return new String(valueDecoded);
}
Then, the encoded string is stored on disk using UTF-8. After
restarting the application, the encoded string is readed from disk and
I'm trying to decode the string using this:
This seems to be a point of failure. Most likely your problem is OS/JDK dependent Apparently the following code seems to work well for me (Win 7, latest JDK 1.8):
public static void main(String[] args) throws IOException {
String source = "{\"configuration\":{\"shop\":{\"name\":\"España\",\"addressLine1\":\"\",\"addressLine2\":\"\"," +
"\"postalCode\":\"\",\"city\":\"\",\"country\":\"\",\"phoneNumber\":\"\"}},\"jointBets\":[]," +
"\"groups\":[{\"name\":\"Test\",\"members\":[]}]}";
// Encode string
String encoded = encryptString(source);
System.out.println("Base64 encoded: " + encoded);
// Temp Dir
String tempDir = System.getProperty("java.io.tmpdir");
// Write to File
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempDir + "data.txt"))) {
writer.write(encoded);
}
// Read from File
Path path = Paths.get(tempDir + "data.txt");
Stream<String> lines = Files.lines(path);
String dataFromFile = lines.collect(Collectors.joining("\n"));
lines.close();
// Compare content
assert encoded.equals(dataFromFile);
// Decode string
String decoded = decryptString(dataFromFile);
System.out.println("Base64 decoded: " + decoded);
}
public static String encryptString(String string) {
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes(StandardCharsets.UTF_8));
return new String(bytesEncoded);
}
public static String decryptString(String string) {
byte[] valueDecoded = Base64.getDecoder().decode(string);
return new String(valueDecoded);
}
Base64 encoded:
eyJjb25maWd1cmF0aW9uIjp7InNob3AiOnsibmFtZSI6IkVzcGHDsWEiLCJhZGRyZXNzTGluZTEiOiIiLCJhZGRyZXNzTGluZTIiOiIiLCJwb3N0YWxDb2RlIjoiIiwiY2l0eSI6IiIsImNvdW50cnkiOiIiLCJwaG9uZU51bWJlciI6IiJ9fSwiam9pbnRCZXRzIjpbXSwiZ3JvdXBzIjpbeyJuYW1lIjoiVGVzdCIsIm1lbWJlcnMiOltdfV19
Base64 decoded:
{"configuration":{"shop":{"name":"España","addressLine1":"","addressLine2":"","postalCode":"","city":"","country":"","phoneNumber":""}},"jointBets":[],"groups":[{"name":"Test","members":[]}]}
My guess is that you are not specifying a charset. Try running the below maybe with and without the charset specified for the String constructor to verify.
#Test
public void base64Test() throws Exception{
String string = "ABCDF";
byte[] bytesEncoded = Base64.getEncoder().encode(string.getBytes());
String encodedStr = (new String(bytesEncoded,Charset.forName("ISO-8859-1")));
System.out.println(encodedStr);
byte[] valueDecoded = Base64.getDecoder().decode(encodedStr);
String decodedStr = (new String(valueDecoded,Charset.forName("ISO-8859-1")));
System.out.println(decodedStr);
}

Java Apache PDFBox - Encryption not deterministic

I have the following code.
public byte[] encryptPdf(byte[] pdf, String password) throws IOException {
ByteArrayOutputStream baos;
try (PDDocument pdDocument = PDDocument.load(pdf)) {
AccessPermission accessPermission = new AccessPermission();
StandardProtectionPolicy protectionPolicy = new
StandardProtectionPolicy(null, password, accessPermission);
protectionPolicy.setEncryptionKeyLength(128);
protectionPolicy.setPermissions(accessPermission);
pdDocument.protect(protectionPolicy);
baos = new ByteArrayOutputStream();
pdDocument.save(baos);
}
return baos.toByteArray();
}
#Test
public void shouldEncryptedPDFEquals() {
byte[] pdf = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("sample.pdf"));
byte[] firstEncryption = encryptPdf(pdf, "token");
byte[] secondEncryption = encryptPdf(pdf, "token");
assertThat(firstEncryption.length, is(secondEncryption.length));
}
Inside a test i will check encrypted documents if there are equals.
The Problem is, that the generates byte array is not deterministic.
If i call the method multiple times, the array length are not ever equals. The assert failed. But not for all types of pdf files.
Is there a bug inside the Apache PDFBox library?

Why doesn't Base64 Encoding of a byte[] in Java work?

import java.io.*;
import java.nio.*;
import java.util.Base64;
import java.util.UUID;
import java.io.UnsupportedEncodingException;
public class Abc {
public static String readFileAsString(String filePath) throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
try {
long len = new java.io.File(filePath).length();
if (len > Integer.MAX_VALUE) throw new IOException("File " + filePath + " too large")
byte[] bytes = new byte[(int) len];
dis.readFully(bytes);
String ans = new String(bytes, "UTF-8");
return ans;
} finally {
dis.close();
}
}
public static void main(String args[]) throws IOException {
String base64encodedString = null;
FileOutputStream stream = new FileOutputStream("C:\\Users\\EMP142738\\Desktop\\New folder\\Readhjbdsdsefd.pdf");
String filePath = new String("C:\\Users\\EMP142738\\Desktop\\New folder\\Readers Quick Ref Card.pdf");
try {
base64encodedString = java.util.Base64.getUrlEncoder().encodeToString(new Abc().readFileAsString(filePath).getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
try {
byte[] base64decodedBytes = java.util.Base64.getUrlDecoder().decode(base64encodedString);
stream.write(base64decodedBytes);
} catch(IOException e){
e.printStackTrace();}
finally {
stream.close();
}//catch (FileNotFoundException e) {
// e.printStackTrace();
}
}
I'm trying to encode and decode a PDF file using Base64. What I'm doing is converting a PDF(Binary File) to a ByteArray, then returning the ByteArray as a string. I'm then encoding this string in Base64, using java.util.Base64. When I try to backtrack through the process, I'm able to convert a PDF(Binary File) but the File is corrupted/damaged. Also, the output file after the entire process ( Encode- Decode) is significantly larger than the input file. I expected that both of them would be of the same size. What am I doing wrong here?
Edit 1( 7/13/16):
In the main method, I modified the code as per Jim's suggestion.
I tried using Base64.encode(byte[] src) after reading the documentation of the same. However it keeps giving the error "cannot find symbol Base64.encode(byte[])". But I've used the encodetoString method from the same Class( java.util.Base64.Encoder). I'm unable to understand the issue here.
Here's the modified main method used after returning a byte[] from the readFileAsString method.
public void main(String args[]) throws IOException {
String filePath = new String("C:\\Users\\EMP142738\\Desktop\\New folder\\Readers Quick Ref Card.pdf");
byte[] src = new Abc().readFileAsString(filePath);
byte[] destination = Base64.encode(src);
}
The problem is in your flow
byte[] -> String -> base64 string
You need to omit the conversion to String and go directly:
byte[] -> base64 string
Converting to String will corrupt a binary stream as it involves a decode operation from the input character set to 16-bit Unicode characters.

Java crypt base64 and compression at the same time

I need some consulting here.
I'm writing a client/server software.
One requirement is to use an XML file to transfer information between the client and the server. This decision was made to allow clients to be created on any language. I know I could use json for simpler communication, but I needed a better Object to Text Mapping, so I ended up with XML. So, to diminish the XMl size problem, I decided to compress it before sending over socket. On top of it, I want to encrypt the data so it will be harder to be broken by some interceptor. I have read a lot about encrypting and encryption types, but for testing purposes I'll just use Base64 and generic compression just to join up all the technologies, than I'll specialize the specifics. I found a lot of code and good advice here on stack exchange, and now I'm having some trouble.
What I have:
In memory Objects;
Static methods to convert Objects to XML in memory;
No use for Serialization because the clients can be written on C, .net, perl, etc;
Avoid disk write to reduce disk I/O, keeping everything in-memory;
The need to work with punctuation chars (UTF-8);
The need to work with stronger encrypt on the future;
The process I idealized is:
Convert object to XML - OK
Establish Client/server communication - OK
Encode XML String to Base64 - OK (no compression)
3.1. Compress XML String and than encode to Base64 - OK
Transfer between client/server - OK
Decode Base64 String to XML String - OK
5.1. Uncompress transferred byte array and decode Base64 - NOT OK
So, I can't find where I'm getting wrong on the "Compress String -> Encode it to Base64 -> transmit -> decode Base64 to String -> uncompress it" process... Here is the snippet from my code "inspired" on stack overflow:
I'm using this answer (with .net compatibility) as a reference to compress/uncompress:
How can I Zip and Unzip a string using GZIPOutputStream that is compatible with .Net?
public class Compressor2 {
public static byte[] compress(String string) throws IOException {
byte[] blockcopy = ByteBuffer
.allocate(4)
.order(java.nio.ByteOrder.LITTLE_ENDIAN)
.putInt(string.length())
.array();
ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(string.getBytes());
gos.close();
os.close();
byte[] compressed = new byte[4 + os.toByteArray().length];
System.arraycopy(blockcopy, 0, compressed, 0, 4);
System.arraycopy(os.toByteArray(), 0, compressed, 4, os.toByteArray().length);
compressed = MyBase64.encode(new String(compressed)).getBytes();
return compressed;
}
public static String decompress(byte[] compressed) throws IOException {
compressed = MyBase64.decode(new String(compressed)).getBytes();
System.out.println(compressed);
System.out.println(new String(compressed));
final int BUFFER_SIZE = 32;
//ByteArrayInputStream is = new ByteArrayInputStream(compressed, 4, compressed.length - 4);
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();
}
from MyBase 64:
public static String encode(String text) throws UnsupportedEncodingException {
byte[] encodedBytes = Base64.encodeBase64(text.getBytes());
return new String(encodedBytes, "UTF-8");
}
public static String decode(String text) throws UnsupportedEncodingException {
byte[] decodedBytes = Base64.decodeBase64(text);
return new String(decodedBytes, "UTF-8");
}
and the test case:
/**
* Test of compress method, of class Compressor2.
*/
#Test
public void testCompress() throws Exception {
System.out.println("compress");
String string = "Hello all, how can I transfer this with punctuation? like á é í ó ú";
byte[] expResult = Compressor2.compress(string);
byte[] result = Compressor2.compress(string);
System.out.write(result);
System.out.print("\n");
System.out.println(new String(result));
assertArrayEquals(expResult, result);
for (byte character : result) {
System.out.print(String.valueOf(character));
}
System.out.print("\n");
for (byte character : result) {
System.out.print((character));
}
System.out.print("\n");
}
/**
* Test of decompress method, of class Compressor2.
*/
#Test
public void testDecompress() throws Exception {
System.out.println("decompress");
String expResult = "Hello all, how can I transfer this with punctuation? like á é í ó ú";
//String expResult = "The lazy dog ate an apple";
byte[] compressed = Compressor2.compress(expResult);
System.out.println(expResult);
System.out.write(compressed);
System.out.print("\n");
System.out.println("going to decompress");
String result = Compressor2.decompress(compressed);
System.out.println(result);
assertEquals(expResult, result);
// TODO punctuation errors?
}
System Out for checking the values:
compress
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
811196565656647118118554873656565656565656565658811811855511181185548785555435777651196955554357868852651001174347118101434711884721181185551118118554811170117434711882771085555435777103561086682851005555435770434347118875310655554357651087410055554357555543578267761181185548799850841181185551118118554871555543575555435777101434711884801181185551118118554999555543575555435785681079099837011712073785269101434711881471101105369788365656565656161
811196565656647118118554873656565656565656565658811811855511181185548785555435777651196955554357868852651001174347118101434711884721181185551118118554811170117434711882771085555435777103561086682851005555435770434347118875310655554357651087410055554357555543578267761181185548799850841181185551118118554871555543575555435777101434711884801181185551118118554999555543575555435785681079099837011712073785269101434711881471101105369788365656565656161
decompress
Hello all, how can I transfer this with punctuation? like á é í ó ú
QwAAAB/vv70IAAAAAAAAAAXvv73vv70N77+9MAwE77+9VX4Adu+/ve+/vTHvv73vv70oFu+/vRMl77+9Mg8lBRUd77+9F++/vW5j77+9AlJd77+977+9RCLvv70Ob2Tvv73vv70G77+977+9Me+/vTPvv73vv71c77+977+9UDkZcSFuxIN4Ee+/vQ/nn5ENSAAAAA==
going to decompress
[B#19f9bdc4
C
Sorry for the long post, I'm trying to give you something to work on to check where I'm getting this wrong. I Appreciate any help...
Edit.: Forgot to say, if you take the "MyBase64.decode or encode" line from the Compressor2 Classe, it works like a charm...

Java: Encode String in quoted-printable

I am looking for a way to quoted-printable encode a string in Java just like php's native quoted_printable_encode() function.
I have tried to use JavaMails's MimeUtility library. But I cannot get the encode(java.io.OutputStream os, java.lang.String encoding) method to work since it is taking an OutputStream as input instead of a String (I used the function getBytes() to convert the String) and outputs something that I cannot get back to a String (I'm a Java noob :)
Can anyone give me tips on how to write a wrapper that converts a String into an OutputStream and outputs the result as a String after encoding it?
To use this MimeUtility method you have to create a ByteArrayOutputStream which will accumulate the bytes written to it, which you can then recover. For example, to encode the string original:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream encodedOut = MimeUtility.encode(baos, "quoted-printable");
encodedOut.write(original.getBytes());
String encoded = baos.toString();
The encodeText function from the same class will work on strings, but it produces Q-encoding, which is similar to quoted-printable but not quite the same:
String encoded = MimeUtility.encodeText(original, null, "Q");
Thats what helps me
#Test
public void koi8r() {
String input = "=?koi8-r?Q?11=5F=F4=ED=5F21=2E05=2Erar?=";
String decode = EncodingUtils.decodeKoi8r(input);
Assertions.assertEquals("11_ТМ_21.05.rar", decode);
}
#Test
public void koi8rWithoutStartTag() {
String input = "=CF=D4=C4=C5=CC=D8=CE=D9=CD =D4=D2=C1=CE=DB=C5=CD =D2=C5=DA=C0=CD=.eml";
String decode = EncodingUtils.decodeKoi8r(input);
Assertions.assertEquals("отдельным траншем резюм=.eml", decode);
}
public static String decodeKoi8r(String text) {
String decode;
try {
decode = MimeUtility.decodeText(text);
} catch (UnsupportedEncodingException e) {
decode = text;
}
if (isQuotedKoi8r(decode)) {
decode = decode(text, "KOI8-R", "quoted-printable", "KOI8-R");
}
return decode;
}
public static boolean isQuotedKoi8r(String text) {
return text.contains("=") || text.toLowerCase().contains("koi8-r");
}
public static String decode(String text, String textEncoding, String encoding, String resultCharset) {
if (text.length() == 0) {
return text;
}
try {
byte[] bytes = text.getBytes(textEncoding);
InputStream decodedStream = MimeUtility.decode(new ByteArrayInputStream(bytes), encoding);
byte[] tmp = new byte[bytes.length];
int n = decodedStream.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return new String(res, resultCharset);
} catch (IOException | MessagingException e) {
return text;
}
}

Categories

Resources