I have a problem converting this Java code that generate md5-base64 to php.
I'd try more then 5 hours but without success.
This is the java code:
public static void main(String[] args) {
// TODO code application logic here
try {
String string = "customString";
String format = "20190101000000";
StringBuilder sb = new StringBuilder();
sb.append(format);
sb.append(string);
String sb2 = sb.toString();
byte[] bytes = sb2.getBytes();
byte[] bArr = new byte[16];
MessageDigest instance2 = MessageDigest.getInstance("MD5");
instance2.update(bytes, 0, bytes.length);
instance2.digest(bArr, 0, 16);
PrintStream printStream6 = System.out;
String a2 = Base64.getEncoder().encodeToString(bArr);
if (a2.length() >= 20) {
a2 = a2.substring(0, 19).trim();
}
StringBuilder sb8 = new StringBuilder();
sb8.append("MD5 16: ");
sb8.append(a2);
printStream6.println(sb8.toString());
} catch (Exception e) {
System.out.println(e);
}
}
And this is my php
<?php
$string = 'customString';
$format = '20190101000000';
$res = $format . $string;
$md5 = md5($res, true);
echo $md5;
echo '------------------';
$base = base64_encode($md5);
echo $base;
echo '------------------';
$result = substr($base, 0, 19);
echo $result;
echo '------------------';
The Java result is 1B2M2Y8AsgTpgAmY7Ph and php is iSKxA+7Y1mMnHhwf0yb
Check for charset encodings. In Java Strings are usually UTF-8 encoded. But when you transform to byte[] in sb2.getBytes(); it is using platform default charset (e.g. ISO-8859-1).
You have to provide the charset in java to have a determined behavior:
sb2.getBytes(java.nio.charset.Charset.forName("UTF-8");
or, the other way round, if goal isn't simply to make both reproduce same output, but you have to implement a PHP solution compatible with your existing Java solution, convert the PHP UTF-8 string to correct charset before md5(...). Therefore use iconv method.
Related
We have a requirement to decompress some data created by a Java system using the DEFLATE algorithm. This we have no control over.
While we don't know the exact variant, we are able to decompress data sent to us using the following Java code:
public static String inflateBase64(String base64)
{
try (Reader reader = new InputStreamReader(
new InflaterInputStream(
new ByteArrayInputStream(
Base64.getDecoder().decode(base64)))))
{
StringWriter sw = new StringWriter();
char[] chars = new char[1024];
for (int len; (len = reader.read(chars)) > 0; )
sw.write(chars, 0, len);
return sw.toString();
}
catch (IOException e)
{
System.err.println(e.getMessage());
return "";
}
}
Unfortunately, our ecosystem is C# based. We're shelling out to the Java program at the moment using the Process object but this is clearly sub-optimal from a performance point of view so we'd like to port the above code to C# if at all possible.
Some sample input and output:
>java -cp . Deflate -c "Pack my box with five dozen liquor jugs."
eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
>java -cp . Deflate -d eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
Pack my box with five dozen liquor jugs.
>
We're told the Java system conforms to RFC 1951 so we've looked at quite a few libraries but none of them seem to decompress the data correctly (if at all). One example is DotNetZip:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ionic.Zlib;
namespace Decomp
{
class Program
{
static void Main(string[] args)
{
// Deflate
String start = "Pack my box with five dozen liquor jugs.";
var x = DeflateStream.CompressString(start);
var res1 = Convert.ToBase64String(x, 0, x.Length);
// Inflate
//String source = "eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y"; // *** FAILS ***
String source = "C0hMzlbIrVRIyq9QKM8syVBIyyxLVUjJr0rNU8jJLCzNL1LIKk0v1gMA";
var part1 = Convert.FromBase64String(source);
var res2 = DeflateStream.UncompressString(part1);
}
}
}
This implements RFC 1951 according to the documentation, but does not decipher the string correctly (presumably due to subtle algorithm differences between implementations).
From a development point of view we could do with understanding the exact variant we need to write. Is there any header information or online tools we could use to provide an initial steer? It feels like we're shooting in the dark a little bit here.
https://www.nuget.org/packages/ICSharpCode.SharpZipLib.dll/
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using System;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string input = "Pack my box with five dozen liquor jugs.";
string encoded = Encode(input);
string decoded = Decode(encoded);
Console.WriteLine($"Input: {input}");
Console.WriteLine($"Encoded: {encoded}");
Console.WriteLine($"Decoded: {decoded}");
Console.ReadKey(true);
}
static string Encode(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
using (MemoryStream inms = new MemoryStream(bytes))
{
using (MemoryStream outms = new MemoryStream())
{
using (DeflaterOutputStream dos = new DeflaterOutputStream(outms))
{
inms.CopyTo(dos);
dos.Finish();
byte[] encoded = outms.ToArray();
return Convert.ToBase64String(encoded);
}
}
}
}
static string Decode(string base64)
{
byte[] bytes = Convert.FromBase64String(base64);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (InflaterInputStream iis = new InflaterInputStream(ms))
{
using (StreamReader sr = new StreamReader(iis))
{
return sr.ReadToEnd();
}
}
}
}
}
}
I have simply code in PHP like that
$hash = md5("testtesttest", TRUE);
echo $hash.'<br>';
$hash = md5($hash . "test", TRUE);
echo $hash.'<br>';
With 2 line fisrt in java, it's working good with my code
public static void main(String[] args) {
// String str = new String(md5x16("test"));
byte[] input = md5x16("testtesttest");
String t = new String(input);
System.out.println(t);
}
public static byte[] md5x16(String text) {
try {
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update(text.getBytes());
byte[] md5Bytes = digester.digest();
return md5Bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
But in line 3 and 4 in PHP, I can't do the same in Java
If I parse to String and add a "test" to it, I will get another result with PHP
Iraklis should be right. md5() gives you a hex-encoded output string by default. You only get the unencoded bytes like in Java by passing in TRUE for the optional $raw_output argument.
the lengths range from 29 to 32
hexString.append( Integer.toHexString(0xFF & message[ i ] ) );
function makeBrokenMD5($s) {
$hash= md5($s, TRUE);
$bytes= preg_split('//', $hash, -1, PREG_SPLIT_NO_EMPTY);
$broken= '';
foreach ($bytes as $byte)
$broken.= dechex(ord($byte));
return $broken;
}`
I am using following code to encrypt my email id in Java and sending it as a parameter in url (Using URLEncoder.encode(encrypteInput("email"))):
public static String encrypteInput(String input) {
String output = null;
input = input + ((int) Math.random()) % 1000;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
output = new String(md5.digest(input.getBytes()));
} catch (Exception e) {
output = "";
}
return output;
}
but, when I am getting the same parameter from servlet, it is not giving me the same output as encrypteInput("email").
Whenever you have a byte array that you want to store in a string, you should be Hex- or Base64-encoding the byte array (hex-encoding is probably better in this particular case).
Apache commons-codec has a Hex class you can use for this:
byte[] bytes = ...
char[] encoded = Hex.encodeHex(bytes);
String encodedString = new String(encoded);
I have an C# function which i want to translate in Java code. I have a problem here:
Encoding enc = Encoding.GetEncoding("Windows-1252");
bytZeichenBenutzer = enc.GetBytes(strBenutzer.Substring(intLoopCount, 1).ToCharArray());
How to do that in Java? I can't find anything similar only stuff that works with UTF-8.
You can use the getBytes(String) or getBytes(Charset) methods:
String myString = getMyStringFromSomeWhere();
byte[] utf8Bytes = myString.getBytes("UTF-8");
// or
Charset myCharset = Charset.forName("Windows-1252");
byte[] windowsBytes = myString.getBytes(myCharset);
String s = "hhh";
try {
s.getBytes("Windows-1252");
} catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
You can do:
byte[] a = "some string".getBytes("Windows-1252");
I'm trying to figure out how to replace binary data using Java.
below is a PHP example of replacing "foo" to "bar" from a swf file.
<?php
$fp = fopen("binary.swf","rb");
$size = filesize("binary.swf");
$search = bin2hex("foo");
$replace = bin2hex("bar");
$data = fread($fp, $size);
$data16 = bin2hex($data);
$data16 = str_replace($search, $replace, $data16);
$data = pack('H*',$data16);
header("Content-Type:application/x-shockwave-flash");
echo $data;
?>
How do I do this in Java.
Try this:
InputStream in = new FileInputStream("filename");
StringBuilder sb = new StringBuilder();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1;) {
sb.append(new String(b, 0, n));
}
in.close();
String data = sb.toString();
data = data.replace("foo", "bar");
//do whatever you want with data
I'm not sure how well this will work with truly binary data (such as a SWF file as used in your example). It's possible that binary data will be interpreted as Unicode characters, and will appear differently if you print them. It's also possible that it will throw some kind of exception for invalid character encodings. You probably want to use a ByteArrayInputStream for binary data, but then you don't have easy ways of doing a search/replace.