How can I make a String Base64 Url Safe Java/Android? - java

I've been trying for a while but I can't seem to get my string to be Url Safe no matter what I do:
Input: XwPp9xazJ0ku5CZnlmgAx2Dld8SHkAeT+d7yvxw=
Desired Output: XwPp9xazJ0ku5CZnlmgAx2Dld8SHkAeT-d7yvxw
Essentially I want to apply some flags on my input string from https://developer.android.com/reference/android/util/Base64.html, namely Base64.URL_SAFE,Base64.NO_PADDING and Base64.NO_WRAP. However when I do:
String str = "XzbeW3jg9NYp6J0w2mTP4NLrTK06p1EDTnNG+KYhvyw=";
byte[] encoded = Base64.encode(
str.getBytes(), Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
byte[] strBytes = Base64.decode(encoded, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
String decoded = new String(strBytes);
//outputs original str "XzbeW3jg9NYp6J0w2mTP4NLrTK06p1EDTnNG+KYhvyw="
System.out.println(decoded);
I am not sure why the url safe encoding isn't working here, is there something I"m doing wrong? Is there a way I can get my desired output (besides manually doing String.replace() and other string modifications?

Thanks for the comments everyone! It was correct that I already had a base64 encoded string and I needed to decode first then re-encode.
byte[] strBytes = Base64.decode(str, Base64.DEFAULT);
byte[] encoded = Base64.encode(
strBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
return new String(encoded);
is the solution that ended up working for me.

Related

Java - encode a string to Base64

I am converting a piece of javascript code to java and want to encode a string to Base64 in java.
Code in javascript:
let encodedData = btoa(String.fromCharCode.apply(null, new Uint8Array(array)))
This converts Uint8Array to string first and then encode it to Base64. But I am not able to find a way to do same in java.
Java code is
InputStream insputStream = new FileInputStream(file);
long length = file.length();
byte[] bytes = new byte[(int) length];
insputStream.read(bytes);
insputStream.close();
byte[] encodedBytes = Base64.getEncoder().encode(bytes);
Which is encoding bytes. Dues to which, encodedData(js) and encodedBytes(java) are not same.
What I want to do is something like:
String str = new String(bytes);
byte[] encodedBytes = Base64.getEncoder().encode(str); // ERROR: encode doesn't accept string
Is there any way to achieve this?
Base64.getEncoder().encode(str.getBytes(Charset)) may help you
(as Thomas noticed). But i can't guess your charset. The right syntax for Charset will be something like StandartCharsets.SOME_CHARSET or Charset.forName("some_charset")

Base64 are removing dots from string

I am trying to transform a string to byte and then get again as string, but the result was different. Have a look:
To decode:
byte[] tokenInBytes = Base64.decode(token, mFlags);
mTokenPreference.put(Base64.encodeToString(tokenInBytes, mFlags));
To get like a string again:
String value = Base64.encodeToString(tokenInBytes, mFlags);
The original string (before decode): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVhMDA2ZTI4OGQ4ZDc1Z
And after was (after encode): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJpZCI6IjVhMDA2ZTI4OGQ4ZDc1Z
Dots was removed. Anyone knows what I did wrong?
The value of mFlags was:
int mFlags = Base64.NO_WRAP | Base64.URL_SAFE | Base64.NO_PADDING;
You can replace your string value (dot) with any letter then after encode and decode replace same letter with dot.
I got this code from this link
// Sending side
byte[] data = value.getBytes("UTF-8");
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
// Receiving side
byte[] data = Base64.decode(base64, Base64.DEFAULT);
String value = new String(data, "UTF-8");

Java: Bits -> Bytes -> String Encoding

In Java, I have a String of bits e.g. "01100111000111...". Next, I want to do the following:
convert string to byte array which I have successfully done using:
byte[] bytes = new BigInteger(bits, 2).toByteArray();
Next, I want to convert bytes to String which I tried to do using:
String byteString = new String(bytes, "UTF-8");
but the results are not correct (garbage characters etc.).
I think "UTF-8" is not the proper encoding.
Kindly tell if there is any other way to get the string from such bytes or the proper encoding.
Edited after your comment:
String string = "01100111000111";
byte[] bytes = new BigInteger(string, 2).toByteArray();
String out = "";
for(byte b: bytes)
out+= String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
System.out.println(out);
output:
0001100111000111
Hope this can help.

Decoding the base64 part in a string in Java

I have encoded into base64 using the Java class built in. But when I try to decode I am having some issues. This code should explain what is happening:
String secondhalf=text.substring(text.length() / 3,text.length() / 3* 2);
byte[] secondhalfByte = secondhalf.getBytes();
secondhalf = Base64.getDecoder().decode(secondhalfByte);
I am getting the error:
cannot convert byte[] to String
What do I do?
To get an encoded string or a decoded byte[] use the following:
String secondhalf=text.substring(text.length() / 3,text.length() / 3* 2);
String encoded = Base64.getEncoder().encodeToString(secondhalf);
byte[] decoded = Base64.getDecoder().decode(encoded);
So you either want to encode your 'secondhalf' into a encoded string or then decode that into a byte[]

C# Android HMAC result

I am using the following code in c# for HMAC conversion:
string RawData = "data";
string sharedKey = "my-key";
byte[] signature = Encoding.UTF8.GetBytes(RawData);
var KeyByteArray = Encoding.UTF8.GetBytes(sharedKey);
using (HMACSHA256 hmac = new HMACSHA256(KeyByteArray))
{
byte[] signatureBytes =hmac.ComputeHash(signature);
var ContentBase64String =(Convert.ToBase64String(signatureBytes));
Console.WriteLine(ContentBase64String );
Console.ReadKey();
}
And the following in Java:
String RawData="data";
String Key="my-key";
byte[] KeyByteArray=Key.getBytes("UTF-8");
byte[] signature=RawData.getBytes("UTF-8");
Mac sha256_HMAC;
sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(KeyByteArray, "HmacSHA256");
sha256_HMAC.init(secret_key);
String ContentBase64String = Base64.encodeToString(sha256_HMAC.doFinal(signature),Base64.URL_SAFE|Base64.NO_WRAP);
The output for C# is as follows:
The output for android is as follows:
I have been it at it for many days and can't figure out what I am doing wrong as the outputs differ though they should be the same.Also, when I remove the - in the key the results are the same. I know I might be missing something simple but thought another pair of eyes might see my mistake. Thanks.
Those answers are the same (as far as the bytes contained in the HMAC goes). For the difference in the + and - characters in the output, you specifically told it to do that by specifying the Base64.URL_SAFE flag.
For future readers of this question: When in doubt, consult the documentation for everything you don't perfectly understand.

Categories