0
votes

Delphi and Java are generate totally different values.

I have MD5 list and I need to encode them with Base64 then URLEncode.

Here is the delphi and java output of the same hash values.

How can I get same as Java output with Delphi?

MD5 Input Value:

BB8C890E3E6372F2720709262BD42BF4

Java Base64 Encoded Output Value :

vIRYPbGf3toJDQehgv3SOamnTNk=

Delphi Base64 Encoded Output Value:

QkI4Qzg5MEUzRTYzNzJGMjcyMDcwOTI2MkJENDJCRjQ=

The delphi code line is:

IdEncoderMIME1.EncodeString('BB8C890E3E6372F2720709262BD42BF4');

And the Java Source is:

String md5 = new String(Base64.encodeBase64(decodedHex));

Full Java Code (That I want to have same results with Delphi): public static void main(String[] args) throws Exception { if ( args.length != 8 ) { usage(); return; }

WebClient webClient = null;

try
{
byte[] decodedHex = Hex.decodeHex(args[0].toCharArray());

String sha1 = new String(Base64.encodeBase64(decodedHex));

decodedHex = Hex.decodeHex(args[1].toCharArray());

String md5 = new String(Base64.encodeBase64(decodedHex));

String rep = args[2];
String comment = args[3];
String Server = args[4];
String ServerPort = args[5];
String username = args[6];
String password = args[7];

String params = "[{\"sha1\":\"" + sha1 + "\",\"md5\":\"" + md5 + "\",\"rep\":\"" + rep + "\",\"comment\":\"" + comment + "\"}]";

// Note the usage of URLEncoder to ensure special characters can be used within the parameters.
String url = "https://" + Server + ":" + ServerPort + "/setRep?fileReps=" + URLEncoder.encode(params, "UTF-8");

System.out.println("\nWeb API params with Base64 values but are not yet URL encoded:");
System.out.println("\n" + params + "\n");
System.out.println("\nWeb API URL call with URL encoded parameters:");
System.out.println("\n" + url + "\n");

webClient = new WebClient(BrowserVersion.FIREFOX_24);

webClient.getOptions().setUseInsecureSSL(true);

DefaultCredentialsProvider userCredentials = (DefaultCredentialsProvider)webClient.getCredentialsProvider();
userCredentials.addCredentials(username, password);
webClient.setCredentialsProvider(userCredentials);

Page setFileRepResponsePage = webClient.getPage(url);

String pageResponse = setFileRepResponsePage.getWebResponse().getContentAsString();

System.out.println("HTTP Status code: " + setFileRepResponsePage.getWebResponse().getStatusCode());
System.out.println(pageResponse);

}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
try
{
webClient.closeAllWindows();
}
catch(Exception ex) {}
}
}
2
What code are you using to convert it? - Adrian Leonhard
The problem can be found in your code, which only you can see. We might guess that you are getting confused between encoding the binary hash5 and its hex representation. Of course, only you can possibly how you want to encode this. So, what are you trying to do? - David Heffernan
I use this line : IdEncoderMIME1.EncodeString('BB8C890E3E6372F2720709262BD42BF4'); - Erkan Sen

2 Answers

2
votes
package main;

import java.io.UnsupportedEncodingException;
import java.util.Base64;

public class test {
    public static void main(String[] args) {
        try {
            // outputs QkI4Qzg5MEUzRTYzNzJGMjcyMDcwOTI2MkJENDJCRjQ=
            System.out.println(Base64.getEncoder()
                .encodeToString("BB8C890E3E6372F2720709262BD42BF4".getBytes("US-ASCII")));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
2
votes
IdEncoderMIME1.EncodeString('BB8C890E3E6372F2720709262BD42BF4');

This takes text input, encodes as ASCII, and then encodes as base64.

String md5 = new String(Base64.encodeBase64(decodedHex));

This takes the binary data in decodedHex and encodes as base64.

As such, your two pieces of code are doing different things. In order for you to make any progress you really need to work out what you want to do. In my view, it makes no sense to take a binary hash, encode as hex, encode as ASCII and then encode as base64.

So I would say that the Delphi code is the problem. You start from the binary hash and base64 encode that. I cannot give you code to do this because you have not given us enough code to work with. For instance, I'm pretty sure that you don't start with 'BB8C890E3E6372F2720709262BD42BF4' as a string literal.

But really your main task here is not to write code, but to get a firm grip on what encodings you should be performing.

FWIW, this confusion between text and binary is one of the great recurring themes in the Delphi tag. I guess it all stemmed from the habit that Delphi programmers adopted of using string as if it were a byte array. This blurring of the distinction between text and binary leads to methods like TIdEncoderMIME.EncodeString which encourages you to think, erroneously, that base64 encoding operates on textual input.


According to your latest edit you wish to decode the hex string to binary, and base64 encode that. Which is done like so in Delphi:

uses
  System.Classes,
  System.NetEncoding;

function HexStringToBase64(const HexStr: string): string;
var
  md5bytes: TBytes;
begin
  SetLength(md5Bytes, Length(HexStr) div 2);
  HexToBin(PChar(HexStr), Pointer(md5Bytes), Length(md5Bytes));
  Result := TNetEncoding.Base64.EncodeBytesToString(md5Bytes);
end;

Now, you won't have TNetEncoding unless you are using XE7 or later. If that is so, choose another base64 library. If you prefer to use the Indy encoder then you'd write it like this:

function HexStringToBase64(const HexStr: string): string;
var
  md5bytes: TIdBytes;
begin
  SetLength(md5Bytes, Length(HexStr) div 2);
  HexToBin(PChar(HexStr), Pointer(md5Bytes), Length(md5Bytes));
  Result := TIdEncoderMIME.EncodeBytes(md5Bytes);
end;

And FWIW, your Java code does not produce the output that you claim it does.