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.
Related
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));
When trying to decrypt a Hex String in Java, I am able to decrypt the string but because the original data which was encrypted is not a String but actually 32 bit hexadecimal values.
The encrypted hex string is "4ba3442d4bc3baf5126b7b271b359e42", and the key used here is "ac00ac00ac00ac00ac00ac00ac00ac00"
The output which im supposed to get as retrieve from aes.online-domain-tools.com is "× z X . b 3 ý . ä g í ý b Þ ." but as seen from this String, only zXb3gb is of a normal ASCII character and the others are the extended characters which in return becomes a � in the console which carries a int value of 65533 which in turn is not correct for my original data.
But if we see the output from aes.online-domain-tools.com, the ASCII VALUES of the extended ASCII characters IS the correct values of the original data but because it is not a normal ASCII character but an extended character, it becomes a � with value 65533 which will give me the wrong value while being casted to integer.
I was wondering rather than decrypting it to a String, am I able to directly decrypt the hex string into the hex string rather than decrypt to string and cast to int.
Currently this is my decryption code:
public static String decrypt(String strToDecrypt)
{
char[] ch=strToDecrypt.toCharArray();
System.out.println("Test: " + ch);
try
{
Cipher cipher2 = Cipher.getInstance("AES/ECB/NoPadding");
cipher2.init(Cipher.DECRYPT_MODE, secretKey);
setDecryptedString(new String(cipher2.doFinal(Hex.decodeHex(ch)))); // Output as String eg: testingone
}
catch (Exception e)
{
System.out.println("Error while decrypting: "+e.toString());
}
return null;
}
And this is the block of code I use to cast it to INT to retrieve the original value:
System.out.println("String To Decrypt : " + strToDecrypt);
final String decryptedString = getDecryptedString();
char[] asciiLine = decryptedString.toCharArray();
for (char ch:asciiLine)
{
System.out.println("Decrypted : " + (int)ch+" ");
}
System.out.println("TestDecrypted : " + test.getDecryptedString());
System.out.println("StringDecrypted : " + decryptedString);
System.out.println("DecodeDecrypted : " + Integer.decode(decryptedString));
your decryption itself seems just fine ... but your handling of the returned data is not...
doFinal returns a byte array
you are handling that by passing it to new String(...)
what you possibly want is to encode that bytearray as a hex number string
have a look here ... How to convert a byte array to a hex string in Java?
I found out a strange problem in converting bytes to UTF8 string in Java.
Why bytes1 and bytes2 are different, but str1 and srt2 is the same?
Here is test code.
import org.apache.commons.codec.binary.Hex;
public class MyTest {
public static void main(String[] args) throws Exception {
byte[] bytes1 = Hex.decodeHex("EDA0BDEDB88A".toCharArray());
byte[] bytes2 = Hex.decodeHex("F09F988A".toCharArray());
System.out.println("bytes1 length: " + bytes1.length);
System.out.println("bytes2 length: " + bytes2.length);
String str1 = new String(bytes1, "utf8");
String str2 = new String(bytes2, "utf8");
System.out.println("str1 is equals str2? " + str1.equals(str2));
}
}
Here is the output of the test code running on jdk7
bytes1 length: 6
bytes2 length: 4
str1 is equals str2? true
Is it possible to find out the relationship between 'EDA0BDEDB88A' and 'F09F988A'?
'F09F988A' is a unicode smail face, but 'EDA0BDEDB88A' is unknown.
Both byte sequences F09F988A and EDA0BDEDB88A are decoded by Java to the same codepoint U+1F60A (SMILING FACE WITH SMILING EYES).
Even if the encoding EDA0BDEDB88A is incorrect, it is accepted by the Java UTF-8 implementation as separate UTF-8 encoding of each of the surrogate code points U+D83D and U+DE0A. This representation is however strictly speaking not allowed in UTF-8, but e.g. defined in CESU-8 ( Compatibility Encoding Scheme for UTF-16).
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.
I find myself in a need to change website platforms from Java to PHP but I'd like to keep all my user's passwords...
I had this code do the password hashing prior to writting the hashed value as the password to the website:
MessageDigest md = null;
md = MessageDigest.getInstance("SHA");
md.update(plaintext.getBytes("UTF-8"));
byte raw[] = md.digest();
hash = new Base64().encodeToString(raw).replaceAll("\n", "").replaceAll("\r", "");
I think the Java code did SHA-1 hashing of the password but just prior to that it was byte encoded to UTF-8 and afterwards it was Base64 encoded.
I'd like to have a PHP code do the same, i.e. return the same value of a hash for the same password as in Java, only it seems that the PHP code doing SHA-1 hashing I have won't return the same SHA(-1, not Base64 encoded, I think?) value when compared to a Java Base64 decoded value of the hash...could it have something to do with the fact that my passwords in PHP are not UTF-8 byte encoded first (and how can I do that in PHP) please?
p.s.
Another strange thing...my passwords in Java are all 28characters long (usually something like this rnwn4zTNgH30l4pP8V05lRVGmF4=)...but the Base64().decode(hash) value of those password hashes is 10 characters long (an example [B#14e1f2b).
I thought Base64 did an additional 1 character to each 3 charters (28 or 27, excluding the padding = charter, is much more that a third larger than those 10 charcters) so am I doing the decoding call wrong somehow maybe???
And on top of all that the SHA-1 password hashed values in PHP are 40 characters long (in a UTF-8 mysql database) like so dd94709528bb1c83d08f3088d4043f4742891f4f?
[B#14e1f2b is definitely not a hash. It's a result of implicit conversion from byte[] to String.
It looks like you do something like this:
String decodedHash = Base64().decode(hash); // Produces [B#14e1f2b
However, the correct representation of the hash is a byte array:
byte[] decodedHash = Base64().decode(hash);
What I normally do with Java to compute a SHA-1 hash that is exactly identical to the PHP sha1() function is the following. The key is that toHexString is used to show the raw bytes in a printable way. If you use the PHP function and want to obtain the same result of your convoluted process, you need to use the parameter $raw_output to true in PHP to get the raw bytes and apply Base64. Full source code.
/**
* Compute a SHA-1 hash of a String argument
*
* #param arg the UTF-8 String to encode
* #return the sha1 hash as a string.
*/
public static String computeSha1OfString(String arg) {
try {
return computeSha1OfByteArray(arg.getBytes(("UTF-8")));
} catch (UnsupportedEncodingException ex) {
throw new UnsupportedOperationException(ex);
}
}
private static String computeSha1OfByteArray(byte[] arg) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(arg);
byte[] res = md.digest();
return toHexString(res);
} catch (NoSuchAlgorithmException ex) {
throw new UnsupportedOperationException(ex);
}
}
private static String toHexString(byte[] v) {
StringBuilder sb = new StringBuilder(v.length * 2);
for (int i = 0; i < v.length; i++) {
int b = v[i] & 0xFF;
sb.append(HEX_DIGITS.charAt(b >>> 4)).append(HEX_DIGITS.charAt(b & 0xF));
}
return sb.toString();
}
PHP's sha1() encodes each byte of the output as hexadecimal by default, but you can get the raw output by passing true as the second argument:
$digest = sha1($password, true); // This returns the same string of bytes as md.digest()
Then pass the digest to base64_encode and you are done:
base64_encode(sha1($password, true));
This returns the exact same SHA-1 hash as your java code.