Java base64 encode, decode yield different results - java

I'm using this:
import com.sun.org.apache.xml.internal.security.utils.Base64; to encode/decode Base64 strings and byte arrays to store into a db.
I'm testing out encoding and decoding to see if I can get back the original string:
SecureRandom srand = new SecureRandom();
byte[] randomSalt = new byte[64];
srand.nextBytes(randomSalt);
System.out.println("rand salt bytes: " + randomSalt); // first line
String salt = Base64.encode(randomSalt);
try {
System.out.println(Base64.decode(salt)); // second line
}catch(Base64DecodingException e){
System.out.println(e);
}
However, this prints out:
rand salt bytes: [B#68286c59
[B#44d01f20
Why are these not the same, so that I can get back the original byte array?

What you are doing is actually dealing with the java pointer instead of the actual bytes.
This is the correct way to implement
byte[] bytesEncoded = Base64.encodeBase64(str .getBytes());
System.out.println("ecncoded value is " + new String(bytesEncoded ));
// Decode data on other side, by processing encoded data
byte[] valueDecoded= Base64.decodeBase64(bytesEncoded );
System.out.println("Decoded value is " + new String(valueDecoded));

Related

Adding a zero byte to the start of a binary hash?

For this question I am asked to:
convert text to hash,
then put it into a byte array,
construct a new byte array 0b, with a zero byte at index 0 then b.
I am able to get the hash of the message c84291b88e8367ef3448899117f8b497f58ac7d43689239783f708ea0092c39b with my code:
MessageDigest md = MessageDigest.getInstance("SHA-256");
//Convert Message to hash
md.update(message1.getBytes());
byte[] digest = md.digest();
String Hash = hexaToString(digest);
System.out.println( "Message 1 in hash is = " + Hash);
And I am able to convert it into a byte array but I am not sure how to add the zerobyte to the start of the byte array?
When computing the digest, you can provide an output array via an overloaded form of digest(). You can allocate an extra byte, and store whatever you like in the extra space at the beginning.
int len = md.getDigestLength();
byte[] digest = new byte[len + 1];
md.digest(digest, 1, len);

Java Base64 Encode function the same as PHP Base64 Encode function?

I'm trying to test a Soap Security header in PHP with values supplied by the client.
They are supplying a value like...
wTAmCL9tmg6KNpeAQOYubw==
...and saying it's a Base64 encoded value.
However, when I run it through PHP's Base64 decode function...
base64_decode("wTAmCL9tmg6KNpeAQOYubw==");
it translates it as: �0&�m6#�.o
If I decode it in Java...
import java.util.Base64;
import java.util.Arrays;
/**
* hello
*/
public class hello {
public static void main(String[] args) {
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
String stringEncoded = "wTAmCL9tmg6KNpeAQOYubw==";
System.out.println("This is a decoded value: " + decoder.decode(stringEncoded));
System.out.println("This is a re-coded value: " + encoder.encode(decoder.decode(stringEncoded)));
}
}
I get a decoded string like this: [B#7229724f
But then if I try to re-encode that string, I get this: [B#4c873330
What am I missing here?
What you are missing is that the result of decoding the Base 64 value is not intended to be printed as a String. In fact, you see this in the output of the Java println. That [B#7229724f is not a string representation of the decoded bytes. It is the way a Java byte [] prints. The [B indicates a byte array, and the remaining characters are the hexadecimal digits of the object identity. (It will print differently for every byte array instance and has nothing to do with the contents of the array.)
If you want the String representation of the bytes you will need to construct a String from the bytes:
System.out.println("This is a decoded value: " + new String(decoder.decode(stringEncoded), StandardCharsets.UTF_8));
System.out.println("This is a re-coded value: " + new String(encoder.encode(decoder.decode(stringEncoded), StandardCharsets.UTF_8));
Based on this answer how about specify the encoding. Recommended encoding is UTF-8.

Java byte array comparison of MessageDigest SHA1 result and original hash value?

I would like to compare two byte arrays. One is calculated from plaintext with MessageDigest SHA1, the other is the hex itself in byte array, without calculation.
MessageDigest returns 20 byte long result, String.getBytes() returns 40 byte long array. bytesToHex() function is the same that was provided in this answer, used only for printing.
The question:
How can I convert a string to byte array (and then compare with one calculated with MessageDigest) without the additional overhead? String comparison with bytesToHex() and .toUppercase() is working, but not an option, since speed is cruital in the application.
The code:
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] toEncode = "test".getBytes();
byte[] encoded = md.digest(toEncode);
System.out.println("String to encode:\t\t" + new String(toEncode));
System.out.println("Encoded in hex:\t\t\t" + bytesToHex(encoded));
System.out.println("Encoded length:\t\t\t" + encoded.length);
byte[] hash = new String("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3").getBytes(); // "test" representation in SHA1
System.out.println("\nHash to compare with:\t\t" + new String(hash));
System.out.println("Hash length:\t\t\t" + hash.length);
System.out.println("Two byte array equals:\t\t" + Arrays.equals(hash, encoded));
System.out.println("Two equals in string:\t\t" + new String(hash).equals(bytesToHex(encoded).toLowerCase()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
The result:
String to encode: test
Encoded in hex: A94A8FE5CCB19BA61C4C0873D391E987982FBBD3
Encoded length: 20
Hash to compare with: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Hash length: 40
Two byte array equals: false
Two equals in string: true
You're not decoding your hex representation to bytes. If you would, for example using the solution from this answer, the two arrays would match:
try {
byte[] encoded = MessageDigest.getInstance("SHA-1").digest("test".getBytes());
byte[] hash = DatatypeConverter.parseHexBinary("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");
System.out.println("Two byte array equals:\t\t" + Arrays.equals(hash, encoded));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

byte[] to String {100,25,28,-122,-26,94,-3,-26}

How can I convert this byte[] to String :
byte[] mytest = new byte[] {100,25,28,-122,-26,94,-3,-26};
i get this : "d��^�" when I use :
new String( mytest , "UTF-8" )
Here is code java for creation of key :
m_key = new javax.crypto.spec.SecretKeySpec(new byte[] {100,25,28,-122,-26,94,-3,-26}, "DES");
Thanks.
In order to decode the byte array into something like ASCII, you need to know its original encoding. Otherwise you would need to treat it as binary.
Note: Base64 is intended for transferring binary data across networks.
I would suggest Base64 encoding your byte array. Then in your PHP code decoding the Base64 string back into a UTF-8 string.
In Java, here's how to Base64 encode your byte array and then decode it back to UTF-8:
import org.apache.commons.codec.binary.Base64;
public class MyTest {
public static void main(String[] args) throws Exception {
byte[] byteArray = new byte[] {100,25,28,-122,-26,94,-3,-26};
System.out.println("To UTF-8 string: " + new String(byteArray, "UTF-8"));
byte[] base64 = Base64.encodeBase64(byteArray);
System.out.println("To Base64 string: " + new String(base64, "UTF-8"));
byte[] decoded = Base64.decodeBase64(base64);
System.out.println("Back to UTF-8 string: " + new String(decoded, "UTF-8"));
/* the decoded byte array is the same as the original byte array */
for (int i = 0; i < decoded.length; i++) {
assert byteArray[i] == decoded[i];
}
}
}
The output from the above code is:
To UTF-8 string: d��^�
To Base64 string: ZBkchuZe/eY=
Back to UTF-8 string: d��^�
So if you wanted to use the same binary data in your PHP code, cut and paste the Base64 string into your PHP code and decode it back to UTF-8. Something like this:
<?php
$str = 'ZBkchuZe/eY=';
$key = base64_decode($str);
echo $key;
?>
I don't code in PHP, but you should be able to decode Base64 using this method:
http://php.net/manual/en/function.base64-decode.php
The above code should echo back the original binary data as UTF-8 (albeit with funny characters). The point is that the funny-looking string in the $key variable is representing the same binary data you had in the Java byte array:
d��^�
You should be able to pass the $key variable into your PHP encryption method.
with the way you are doing it makes no sense imo. you are creating a new string with the byte[] as an argument. i dont think that function is suppose to parse. so what you end up with is a lot of junk. but a little bit of googling got me this: http://www.mkyong.com/java/how-do-convert-byte-array-to-string-in-java/
Would m_key.getEncoded() give you the desired result.
Javadocs - SecretKeySpec
If not, you have to identify the Key provider that was used for the encoding (which resulted in the byte array that you have now) and decode.

byte to string and vice versa

I need to convert a salt value randomly generated and store it in the database. To store it in the database I converted it to a string. Then for retrieving the original value, I convert it back to byte. But both value are not matching. I have tried "UTF-8","UTF-16", BASE64Encoder.
SecureRandom ranGen = new SecureRandom();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);
System.out.println(aesKey);
String a=new String(aesKey,"UTF-16");
byte[] b=new byte[16];
b=a.getBytes("UTF-16");
System.out.println(b);
Outputs for the above code(Executed it 2 times):
[B#11563ff
[B#1581593
and
[B#170888e
[B#11563ff
You really ought to use Base64 for converting binary data to Strings. There are lots of free implementations available, for example the one found in Apache Commons Codec.
Also, it's really easy to use, for example:
For encoding:
import org.apache.commons.codec.binary.Base64;
...
byte[] abValue = {...}; // Your data to encode
Base64 base64 = new Base64();
String strEncodedData = base64.encodeToString(abValue).trim();
For decoding:
import org.apache.commons.codec.binary.Base64;
...
String strEncodedData = "..."; // Your previously encoded data
Base64 base64 = new Base64();
byte[] abValue = base64.decode(strValue);
As your code is written above, printing aesKey and then b, what you are actually printing is the output of the toString method for an array object, which is just the default Object toString method. So I don't see how you can expect them to be the same.
If you really want to check they are the same you should compare them byte by byte.
In terms of your actual question regarding storing a byte[] as a String in the DB, your best bet is to Base64 encode it. I would suggest using the Apache Commons Codec library for this. See the user guide.
EDIT:
Using the BASE64Encode and BASE64Decoder you have referred to, the code would be like this:
SecureRandom ranGen = new SecureRandom();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);
String a = new BASE64Encoder().encode(aesKey);
System.out.println(a);
byte[] b = new BASE64Decoder().decodeBuffer(a);
System.out.println(new BASE64Encoder().encode(b));
for (int i = 0; i < aesKey.length; i++) {
System.out.println(aesKey[i] + " " + b[i]);
}
Here, I have also looped through the bytes individually, to show that they are indeed equal.

Categories

Resources