2

I am trying to convert a bitcoin address and have the following code from here (Calculate Segwit address from public address, 2nd answer):

Step1: $ printf 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 > adr.txt
Step2: $ printf $( cat adr.txt | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) >adr.hex
Step3: $ openssl dgst -sha256 -binary <adr.hex >tmp_sha256.hex
Step4: $ openssl dgst -ripemd160  <tmp_sha256.hex
## result should be: 56379c7bcd6b41188854e74169f844e8676cf8b8

Now I want to do this in Java. I currently have the following code. No matter what I try, I dont get the correct result. :(

String address = "1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9"; // step 1
System.out.println("address: " + address);
String addressHex = toHex(address);
System.out.println("address hex: " + addressHex);
byte[] addressBytes = addressHex.getBytes(StandardCharsets.UTF_8); // step 2
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(addressBytes); // step 3
RIPEMD160Digest digest2 = new RIPEMD160Digest(); // steps 4
digest2.update(hash, 0, hash.length);
byte[] out = new byte[20];
digest2.doFinal(out, 0);
System.out.println("result: " + bytesToHex(out)); // = 62ab42cba5d2632d1350fafb2587f5d2ece445d3
                                                  // should be 56379c7bcd6b41188854e74169f844e8676cf8b8

Output:

address: 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9
address hex: 314c383853323643356f796a4c31676b58734265597748486a764776436369647239
result: 62ab42cba5d2632d1350fafb2587f5d2ece445d3

Can someone help me? I think the problem is somewhere doing the conversion String/hex/byte ...? I tried really hard, but cannot find the correct way to do it.

I also tried to convert the address to hex and after that to bytes, but doesnt work neither. :/

// updated post ... still doesnt show the correct result :/

// update2:

byte[] address = ("1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9").getBytes();
System.out.println("address byte array: " + address);
String addressHex = bytesToHex(address);
System.out.println("address hex: " + addressHex);
byte[] addressBytes = addressHex.getBytes();
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(addressBytes);
RIPEMD160Digest digest2 = new RIPEMD160Digest();
digest2.update(hash, 0, hash.length);
byte[] out = new byte[20];
digest2.doFinal(out, 0);
System.out.println("result: " + bytesToHex(out));

Output

address byte array: [B@108c4c35
address hex: 314c383853323643356f796a4c31676b58734265597748486a764776436369647239
result: 62ab42cba5d2632d1350fafb2587f5d2ece445d3
1
  • Please read my answer in the original question you linked, the code you are trying to convert is wrong in the first place
    – meshcollider
    Dec 31, 2017 at 0:11

3 Answers 3

1

Ok, here is the plain code for conversion from legacy to segwit:

    String addressToConvert = "1BGJEft81aaudqaCCcNnhsRQBA3Y96KYtx";
    byte[] decoded = org.bitcoinj.core.Utils.parseAsHexOrBase58(addressToConvert);
    // We should throw off header byte that is 0 for Bitcoin (Main)
    byte[] pureBytes = new byte[20];
    System.arraycopy(decoded, 1, pureBytes, 0, 20);
    // Than we should prepend the following bytes:
    byte[] scriptSig = new byte[pureBytes.length + 2];
    scriptSig[0] = 0x00;
    scriptSig[1] = 0x14;
    System.arraycopy(pureBytes, 0, scriptSig, 2, pureBytes.length);
    byte[] addressBytes = org.bitcoinj.core.Utils.sha256hash160(scriptSig);
    // Here are the address bytes
    byte[] readyForAddress = new byte[addressBytes.length + 1 + 4];
    // prepending p2sh header:
    readyForAddress[0] = (byte) 5;
    System.arraycopy(addressBytes, 0, readyForAddress, 1, addressBytes.length);
    // But we should also append check sum:
    byte[] checkSum = Sha256Hash.hashTwice(readyForAddress, 0, addressBytes.length + 1);
    System.arraycopy(checkSum, 0, readyForAddress, addressBytes.length + 1, 4);
    // To get the final address:
    String segwitAddress = Base58.encode(readyForAddress);

Functions (like org.bitcoinj.core.Utils.parseAsHexOrBase58) are taken from bitcoinJ library, as I mentioned earlier.

The resulting address is 3G7YPGDLLeaf1R36wrVxnSAhWMaA81oNhJ. It can be checked here: Bip39 with mnemonic: "hood fatal cabbage proud lift amazing today mom disorder decorate eternal action punch finish drop thing chicken host erode bean rescue oblige mango double". To do that you should select "BIP49" and see the produced segwit address. Corresponding legacy address can be found at BIP32 tab, but you should manually insert derivation path m/49'/0'/0'/0. Note that private keys for them are equal: L38zkVFvLmVmHTpFdqfSP2WrQ1qcZnB829rthRS1rRexcc7RKuHr

Your address 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 is converted to 39gGJc9HiemSJwpa2smXgCXMW8y9FNzFDe.

1
  • How can I give you 10M upvotes? Thanks! Works perfectly! TY TY TY!
    – A.c
    Dec 30, 2017 at 17:16
1

Address is in Base58 format. So, if you want to fet hex representation, you should firstly convert base58-address string to byte array and then convert it to hex string. bitcoinJ library has utilities for that, you can find all of the conversions there.

1
  • Thanks! I tried to implement your suggestion but I am still not able to get the correct result. I updated my post ("update2"). ty!
    – A.c
    Dec 30, 2017 at 12:20
1

I have not the Java solution, but I can indicate the error. The conversion to hex is apparently missing. When I do the hash on the text file itself, I also get the wrong result:

$ printf 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 > adr.txt
$ openssl dgst -sha256 -binary <adr.txt >tmp_sha256.hex
$ openssl dgst -ripemd160  <tmp_sha256.hex
(stdin)= db151e871af66b1323893e3f527e22f7684718af

so the transformation into a hex byte array "addressHex" is for sure missing something.

Update:

I can see the "bytesToHex()" function, was this the code from the link I provided in the other thread? If so, try to dump the output of your java into a file, and use hexdump to verify. So you can concentrate on these two lines (I made the sed command shorter, without "cat"):

$ printf 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 > adr.txt
$ printf $( sed 's/[[:xdigit:]]\{2\}/\\x&/g' adr.txt ) >adr.hex
$ hexdump -C adr.hex 
00000000  31 4c 88 53 26 c5 6f 79  6a 4c 31 67 6b 58 73 be  |1L.S&.oyjL1gkXs.|
00000010  59 77 48 48 6a 76 47 76  cc 69 64 72 39           |YwHHjvGv.idr9|
0000001d

Here you should receive the same result by your java code, then you'd be good to go :-)

3
  • Thanks, I edited my code but it still doesnt work. I have also edited my post to now show the new code.
    – A.c
    Dec 30, 2017 at 11:05
  • see my update, that's so far all I can do ... Dec 30, 2017 at 12:37
  • Please listen to my answer in the other thread, the approach is completely wrong from the start and you may end up losing funds if you use it. You should not be hashing the address at all
    – meshcollider
    Dec 31, 2017 at 0:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.