Base 64 encoding issue.(unexpected plus marks) [duplicate] - java

https://web.archive.org/web/20110422225659/https://en.wikipedia.org/wiki/Base64#URL_applications
talks about base64Url - Decode
a modified Base64 for URL variant exists, where no padding '=' will be used, and the '+' and '/' characters of standard Base64 are respectively replaced by '-' and '_'
I created the following function:
public static String base64UrlDecode(String input) {
String result = null;
BASE64Decoder decoder = new BASE64Decoder();
try {
result = decoder.decodeBuffer(input.replace('-','+').replace('/','_')).toString();
}
catch (IOException e) {
System.out.println(e.getMessage());
}
return result;
}
it returns a very small set of characters that don't even resemble to the expected results.
any ideas?

Java8+
import java.util.Base64;
return Base64.getUrlEncoder().encodeToString(bytes);

Base64 encoding is part of the JDK since Java 8. URL safe encoding is also supported with java.util.Base64.getUrlEncoder(), and the "=" padding can be skipped by additionally using the java.util.Base64.Encoder.withoutPadding() method:
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public String encode(String raw) {
return Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(raw.getBytes(StandardCharsets.UTF_8));
}

With the usage of Base64 from Apache Commons, who can be configured to URL safe, I created the following function:
import org.apache.commons.codec.binary.Base64;
public static String base64UrlDecode(String input) {
String result = null;
Base64 decoder = new Base64(true);
byte[] decodedBytes = decoder.decode(input);
result = new String(decodedBytes);
return result;
}
The constructor Base64(true) makes the decoding URL-safe.

In the Android SDK, there's a dedicated flag in the Base64 class: Base64.URL_SAFE, use it like so to decode to a String:
import android.util.Base64;
byte[] byteData = Base64.decode(body, Base64.URL_SAFE);
str = new String(byteData, "UTF-8");

Guava now has Base64 decoding built in.
https://google.github.io/guava/releases/17.0/api/docs/com/google/common/io/BaseEncoding.html

public static byte[] encodeUrlSafe(byte[] data) {
byte[] encode = Base64.encode(data);
for (int i = 0; i < encode.length; i++) {
if (encode[i] == '+') {
encode[i] = '-';
} else if (encode[i] == '/') {
encode[i] = '_';
}
}
return encode;
}
public static byte[] decodeUrlSafe(byte[] data) {
byte[] encode = Arrays.copyOf(data, data.length);
for (int i = 0; i < encode.length; i++) {
if (encode[i] == '-') {
encode[i] = '+';
} else if (encode[i] == '_') {
encode[i] = '/';
}
}
return Base64.decode(encode);
}

Right off the bat, it looks like your replace() is backwards; that method replaces the occurrences of the first character with the second, not the other way around.

#ufk's answer works, but you don't actually need to set the urlSafe flag when you're just decoding.
urlSafe is only applied to encode operations. Decoding seamlessly
handles both modes.
Also, there are some static helpers to make it shorter and more explicit:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
public static String base64UrlDecode(String input) {
StringUtils.newStringUtf8(Base64.decodeBase64(input));
}
Docs
newStringUtf8()
decodeBase64()

This class can help:
import android.util.Base64;
public class Encryptor {
public static String encode(String input) {
return Base64.encodeToString(input.getBytes(), Base64.URL_SAFE);
}
public static String decode(String encoded) {
return new String(Base64.decode(encoded.getBytes(), Base64.URL_SAFE));
}
}

I know the answer is already there, but still, if someone wants...
import java.util.Base64; public
class Base64BasicEncryptionExample {
publicstaticvoid main(String[] args) {
// Getting encoder
Base64.Encoder encoder = Base64.getUrlEncoder();
// Encoding URL
String eStr = encoder.encodeToString
("http://www.javatpoint.com/javatutorial/".getBytes());
System.out.println("Encoded URL: "+eStr);
// Getting decoder
Base64.Decoder decoder = Base64.getUrlDecoder();
// Decoding URl
String dStr = new String(decoder.decode(eStr));
System.out.println("Decoded URL: "+dStr);
}
}
Took help from: https://www.javatpoint.com/java-base64-encode-decode

In Java try the method Base64.encodeBase64URLSafeString() from Commons Codec library for encoding.

Related

How to obtain the Base64 representation of a string in Android Oreo

I need to convert string into base64 under Oreo api level.
I have the following code:
public String genAuthKey(String u, String p){
user = u;
pass = p;
key = user+":"+pass;
byte[] encodedBytes = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
encodedBytes = Base64.getEncoder().encode(key.getBytes());
Log.e("VERSION IS","O");
}else{
encodedBytes = Base64.getEncoder().encodeToString(key.getBytes()).getBytes();
Log.e("VERSION LESS","O");
}
Log.e("key",new String(encodedBytes,Charset.forName("UTF-8")));
return new String(encodedBytes, Charset.forName("UTF-8"));
}
In else condition, I need code to convert and send the data properly. How can I do that?
first add this import
import android.util.Base64;
then replace your method with a version agnostic variant
public String genAuthKey(String u, String p) {
user = u;
pass = p;
key = user + ":" + pass;
byte[] encodedBytes = Base64.encode(key.getBytes(), Base64.DEFAULT);
Log.e("key", new String(encodedBytes, StandardCharsets.UTF_8));
return new String(encodedBytes, StandardCharsets.UTF_8);
}
Enjoy!
Try this code for encoding kotlin:
var encodedString = Base64.encode("Your String", Base64.DEFAULT).toString(Charsets.UTF_8)
and for decoding:
var decodedString = Base64.decode(encodedString, Base64.DEFAULT).toString(Charsets.UTF_8)

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);
}

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: 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;
}
}

Java base64 encoding output from Apache Common the "wrong" result

I am trying to use the Base64 encoding functionality from Apache Common. But I seem to get the "wrong" result. The doc is here.
My code is like this:
import org.apache.commons.codec.binary.Base64;
String data = "hi,all,how can this happen?";
byte[] databytes = Base64.encodeBase64(data.getBytes());
data = databytes.toString();
System.out.println(data);
//the result is:
//[B#121cc40
However I encode the same string using Python, the code is:
import base64
print base64.b64encode("hi,all,how can this happen?")
#The result is aGksYWxsLGhvdyBjYW4gdGhpcyBoYXBwZW4/
How can there be such difference?
That's not how you print a byte (or any other type of) array in Java, if you want to view its contents.
This is:
System.out.println(Arrays.toString(data));
import org.apache.commons.codec.binary.Base64;
public class Codec {
public static void main(String[] args) {
try {
String data = "hi,all,how can this happen?";
String encodedText;
// Base64
encodedText = new String(Base64.encodeBase64(data.getBytes()));
System.out.println("Encoded: " + encodedText);
System.out.println("Decoded:"
+ new String(Base64.decodeBase64(encodedText.getBytes())));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Now it will encode your String data
You are printing the address.
If you want to print the String data, you can use,
String password = new String(databytes);
System.out.println("Encoded String "+ password)

Categories

Resources