I got some encoded log information, casted into a string for transmitting purpose (the cast might be ugly but it works).
I'm trying to cast it back to a byte[] in order to decode it but it's not working:
byte[] encodedBytes = android.util.Base64.encode((login + ":" + password).getBytes(), NO_WRAP);
String encoded = "Authentification " + encodedBytes;
String to_decode = encoded.substring(17);
byte[] cast1 = to_decode; // error
byte[] cast2 = (byte[]) to_decode; // error
byte[] cast3 = to_decode.getBytes();
// no error, but i get something totally different from encodedBytes (the array is even half the size of encodedBytes)
// and when i decode it i got an IllegalArgumentException
these 3 casts are not working, any idea?
There are multiple problems here.
In general, you need to use Base64.decode in order to reverse the result of Base64.encode:
byte[] data = android.util.Base64.decode(to_decode, DEFAULT);
In general, you should always ask yourself "How did I perform the conversion from type X to type Y?" when working out how to get back from type Y to type X.
Note that you've got a typo in your code too - "Authentification" should be "Authentication".
However, you've also got a problem with your encoding - you're creating a byte[], and using string concatenation with that will call toString() on the byte array, which is not what you want. You should call encodeToString instead. Here's a complete example:
String prefix = "Authentication "; // Note fix here...
// TODO: Don't use basic authentication; it's horribly insecure.
// Note the explicit use of ASCII here and later, to avoid any ambiguity.
byte[] rawData = (login + ":" + password).getBytes(StandardCharsets.US_ASCII);
String header = prefix + Base64.encodeToString(rawData, NO_WRAP);
// Now to validate...
String toDecode = header.substring(prefix.length());
byte[] decodedData = Base64.decode(toDecode, DEFAULT);
System.out.println(new String(decodedData, StandardCharsets.US_ASCII));
Related
I'm converting an old VB.net project to Java (I barely know any VB).
Dim asciis As Byte() = System.Text.Encoding.ASCII.GetBytes(name)
For i As Int32 = 0 To asciis.Length - 1
asciis(i) = CByte(asciis(i) + 1)
Next
Dim encryptedName As String = StrReverse(Uri.EscapeDataString(System.Text.Encoding.ASCII.GetString(asciis, 0, asciis.Count())))
I converted it to:
byte[] asciis = name.getBytes();
for (int i =0; i<asciis.length-1;i++){
asciis[i] = (byte)(asciis[i]+1);
}
String encryptedName = StringUtils.reverse(asciis.toString()).substring(0,asciis.length);
I converted the name 29384 and the .Net gives 594A3%3 while my Java code gives d9354.
What am I missing?
This asciis.toString() is not correct (it will give you the adress of the array instead), you need to do new String(asciis, StandardCharsets.UTF_8) to create the String from the array of bytes. And you need to apply URLEncoder.encode(newString, StandardCharsets.UTF_8.name()) to apply the same URI encoding that is done in your VB code. Also you need to do name.getBytes(StandardCharsets.UTF_8) instead of just name.getBytes(), because else you'll use the default charset of the operating system it's running on, and it might not be ASCII compatible.
Alright as #Nyamiou said I had to give the charset to the String and encode it with an URLEncoder.
byte[] asciis = number.getBytes(Charset.forName("US-ASCII"));
for (int i =0; i<asciis.length;i++){
asciis[i] = (byte)(asciis[i]+1);
}
String asciiString = new String(asciis, Charset.forName("US-ASCII"));
String encryptedNumber= StringUtils.reverse(URLEncoder.encode(asciiString, "US-ASCII"));
I'm trying to save content of a pdf file in a json and thought of saving the pdf as String value converted from byte[].
byte[] byteArray = feature.convertPdfToByteArray(Paths.get("path.pdf"));
String byteString = new String(byteArray, StandardCharsets.UTF_8);
byte[] newByteArray = byteString.getBytes(StandardCharsets.UTF_8);
String secondString = new String(newByteArray, StandardCharsets.UTF_8);
System.out.println(secondString.equals(byteString));
System.out.println(Arrays.equals(byteArray, newByteArray));
System.out.println(byteArray.length + " vs " + newByteArray.length);
The result of the above code is as follows:
true
false
421371 vs 760998
The two String's are equal while the two byte[]s are not. Why is that and how to correctly convert/save a pdf inside a json?
You are probably using the wrong charset when reading from the PDF file.
For example, the character é (e with acute) does not exists in ISO-8859-1 :
byte[] byteArray = "é".getBytes(StandardCharsets.ISO_8859_1);
String byteString = new String(byteArray, StandardCharsets.UTF_8);
byte[] newByteArray = byteString.getBytes(StandardCharsets.UTF_8);
String secondString = new String(newByteArray, StandardCharsets.UTF_8);
System.out.println(secondString.equals(byteString));
System.out.println(Arrays.equals(byteArray, newByteArray));
System.out.println(byteArray.length + " vs " + newByteArray.length);
Output :
true
false
1 vs 3
Why is that
If the byteArray indeed contains a PDF, it most likely is not valid UTF-8. Thus, wherever
String byteString = new String(byteArray, StandardCharsets.UTF_8);
stumbles over a byte sequence which is not valid UTF-8, it will replace that by a Unicode replacement character. I.e. this line damages your data, most likely beyond repair. So the following
byte[] newByteArray = byteString.getBytes(StandardCharsets.UTF_8);
does not result in the original byte array but instead a damaged version of it.
The newByteArray, on the other hand, is the result of UTF-8 encoding a given string, byteString. Thus, newByteArray is valid UTF-8 and
String secondString = new String(newByteArray, StandardCharsets.UTF_8);
does not need to replace anything outside the UTF-8 mappings, in particular byteString and secondString are equal.
how to correctly convert/save a pdf inside a json?
As #mammago explained in his comment,
JSON is not the appropriate format for binary content (like files). You should propably use something like base64 to create a string out of your PDF and store that in your JSON object.
I was trying to print encrypted text using string perhaps i was wrong somewhere. I am doing simple xor on a plain text. Coming encrypted text/string i am putting in a C program and doing same xor again to get plain text again.
But in between, I am not able to get proper string of encrypted text to pass in C
String xorencrypt(byte[] passwd,int pass_len){
char[] st = new char[pass_len];
byte[] crypted = new byte[pass_len];
for(int i = 0; i<pass_len;i++){
crypted[i] = (byte) (passwd[i]^(i+1));
st[i] = (char)crypted[i];
System.out.println((char)passwd[i]+" "+passwd[i] +"= " + (char)crypted[i]+" "+crypted[i]);/* characters are printed fine but problem is when i am convering it in to string */
}
return st.toString();
}
I don't know if any kind of encoding also needed because if i did so how I will decode and decrypt from C program.
example if suppose passwd = bond007
then java program should return akkb78>
further C program will decrypt akkb78> to bond007 again.
Use
return new String(crypted);
in that case you don't need st[] array at all.
By the way, the encoded value for bond007 is cmm`560 and not what you posted.
EDIT
While solution above would most likely work in most java environments, to be safe about encoding,
as suggested by Alex, provide encoding parameter to String constructor.
For example if you want your string to carry 8-bit bytes :
return new String(crypted, "ISO-8859-1");
You would need the same parameter when getting bytes from your string :
byte[] bytes = myString.getBytes("ISO-8859-1")
Alternatively, use solution provided by Alex :
return new String(st);
But, convert bytes to chars properly :
st[i] = (char) (crypted[i] & 0xff);
Otherwise, all negative bytes, crypted[i] < 0 will not be converted to char properly and you get surprising results.
Change this line:
return st.toString();
with this
return new String(st);
I have a
String b = "[B#64964f8e";
this is the byte[] output which i store in a string
Now I would like to convert it back to byte[]
byte[] c = b.getBytes();
but it gave me different byte which is
[B#9615a1f
how can I get back the same as [B#64964f8e ?
String b = "[B#64964f8e";
that's not a real string. That's the type and address of your byte array. It's nothing more than a transient reference code, and if the original array was GC'd you wouldn't even have a hope of getting it back with really funky native methods romping through memory.
I suspect you are trying to do the wrong thing and this won't help you at all because I would have though you want the contents to be the same, not the result of the toString() method.
You shouldn't be using a text String to binary data but you can use ISO-8859-1
byte[] bytes = random bytes
String text = new String(bytes, "ISO-8859-1");
byte[] bytes2 = text.getBytes("ISO-8859-1"); // gets back the same bytes.
But to answer your question, you can do this.
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
byte[] bytes = new byte[0];
unsafe.putInt(bytes, 1L, 0x64964f8e);
System.out.println(bytes);
prints
[B#64964f8e
"[B#64964f8e" is not a string encoding of your byte[]. That is the result of the default toString() implementation, which tells you the type and reference location. Maybe you wanted to use base64-encoding instead, e.g. using javax.xml.bind.DatatypeConverter's parseBase64Binary() and printBase64Binary():
byte[] myByteArray = // something
String myString = javax.xml.bind.DatatypeConverter.printBase64Binary(myByteArray);
byte[] decoded = javax.xml.bind.DatatypeConverter.parseBase64Binary(myString);
// myByteArray and decoded have the same contents!
A simple answer is:
System.out.println(c) prints the reference's representation of c object. Not c's content.(Only in cases where Object's toString() method is not overriden)
String b = "[B#64964f8e";
byte[] c = b.getBytes();
System.out.println(c); //prints reference's representation of c
System.out.println(new String(c)); //prints [B#64964f8e
Is it possible to convert a string to a byte array and then convert it back to the original string in Java or Android?
My objective is to send some strings to a microcontroller (Arduino) and store it into EEPROM (which is the only 1 KB). I tried to use an MD5 hash, but it seems it's only one-way encryption. What can I do to deal with this issue?
I would suggest using the members of string, but with an explicit encoding:
byte[] bytes = text.getBytes("UTF-8");
String text = new String(bytes, "UTF-8");
By using an explicit encoding (and one which supports all of Unicode) you avoid the problems of just calling text.getBytes() etc:
You're explicitly using a specific encoding, so you know which encoding to use later, rather than relying on the platform default.
You know it will support all of Unicode (as opposed to, say, ISO-Latin-1).
EDIT: Even though UTF-8 is the default encoding on Android, I'd definitely be explicit about this. For example, this question only says "in Java or Android" - so it's entirely possible that the code will end up being used on other platforms.
Basically given that the normal Java platform can have different default encodings, I think it's best to be absolutely explicit. I've seen way too many people using the default encoding and losing data to take that risk.
EDIT: In my haste I forgot to mention that you don't have to use the encoding's name - you can use a Charset instead. Using Guava I'd really use:
byte[] bytes = text.getBytes(Charsets.UTF_8);
String text = new String(bytes, Charsets.UTF_8);
You can do it like this.
String to byte array
String stringToConvert = "This String is 76 characters long and will be converted to an array of bytes";
byte[] theByteArray = stringToConvert.getBytes();
http://www.javadb.com/convert-string-to-byte-array
Byte array to String
byte[] byteArray = new byte[] {87, 79, 87, 46, 46, 46};
String value = new String(byteArray);
http://www.javadb.com/convert-byte-array-to-string
Use [String.getBytes()][1] to convert to bytes and use [String(byte[] data)][2] constructor to convert back to string.
byte[] pdfBytes = Base64.decode(myPdfBase64String, Base64.DEFAULT)
import java.io.FileInputStream;
import java.io.ByteArrayOutputStream;
public class FileHashStream
{
// write a new method that will provide a new Byte array, and where this generally reads from an input stream
public static byte[] read(InputStream is) throws Exception
{
String path = /* type in the absolute path for the 'commons-codec-1.10-bin.zip' */;
// must need a Byte buffer
byte[] buf = new byte[1024 * 16]
// we will use 16 kilobytes
int len = 0;
// we need a new input stream
FileInputStream is = new FileInputStream(path);
// use the buffer to update our "MessageDigest" instance
while(true)
{
len = is.read(buf);
if(len < 0) break;
md.update(buf, 0, len);
}
// close the input stream
is.close();
// call the "digest" method for obtaining the final hash-result
byte[] ret = md.digest();
System.out.println("Length of Hash: " + ret.length);
for(byte b : ret)
{
System.out.println(b + ", ");
}
String compare = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
String verification = Hex.encodeHexString(ret);
System.out.println();
System.out.println("===")
System.out.println(verification);
System.out.println("Equals? " + verification.equals(compare));
}
}