Convertir entre String/Hex/Byte en Java para sha256 - ¿formato incorrecto?

Estoy tratando de convertir una dirección de bitcoin y tengo el siguiente código de aquí ( Calcular la dirección de Segwit desde la dirección pública , segunda respuesta):

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

Ahora quiero hacer esto en Java. Actualmente tengo el siguiente código. No importa lo que intento, no obtengo el resultado correcto. :(

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

Producción:

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

¿Alguien me puede ayudar? Creo que el problema está en alguna parte haciendo la conversión String/hex/byte...? Lo intenté muy duro, pero no puedo encontrar la manera correcta de hacerlo.

También traté de convertir la dirección a hexadecimal y luego a bytes, pero tampoco funcionó. :/

// publicación actualizada... aún no muestra el resultado correcto :/

// actualizar2:

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));

Producción

address byte array: [B@108c4c35
address hex: 314c383853323643356f796a4c31676b58734265597748486a764776436369647239
result: 62ab42cba5d2632d1350fafb2587f5d2ece445d3
Lea mi respuesta en la pregunta original que vinculó, el código que está tratando de convertir es incorrecto en primer lugar

Respuestas (3)

Ok, aquí está el código simple para la conversión de legado a 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);

Las funciones (como org.bitcoinj.core.Utils.parseAsHexOrBase58) se toman de la biblioteca bitcoinJ , como mencioné anteriormente.

La dirección resultante es 3G7YPGDLLeaf1R36wrVxnSAhWMaA81oNhJ . Se puede comprobar aquí: Bip39 con mnemotécnico: "capucha fatal repollo orgulloso levantar increíble hoy mamá desorden decorar eterno acción puñetazo terminar soltar cosa pollo anfitrión erosionar frijol rescate obligar mango doble". Para hacer eso, debe seleccionar "BIP49" y ver la dirección de segwit producida. La dirección heredada correspondiente se puede encontrar en la pestaña BIP32, pero debe insertar manualmente la ruta de derivación m/49'/0'/0'/0. Tenga en cuenta que las claves privadas para ellos son iguales: L38zkVFvLmVmHTpFdqfSP2WrQ1qcZnB829rthRS1rRexcc7RKuHr

Su dirección 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 se convierte en 39gGJc9HiemSJwpa2smXgCXMW8y9FNzFDe .

¿Cómo puedo darte 10 millones de votos a favor? ¡Gracias! ¡Funciona perfectamente! TY TY TY!

La dirección está en formato Base58. Por lo tanto, si desea obtener una representación hexadecimal, primero debe convertir la cadena de dirección base58 en una matriz de bytes y luego convertirla en una cadena hexadecimal. La biblioteca bitcoinJ tiene utilidades para eso, puede encontrar todas las conversiones allí.

¡Gracias! Traté de implementar su sugerencia, pero todavía no puedo obtener el resultado correcto. Actualicé mi publicación ("update2"). ty!

No tengo la solución Java, pero puedo indicar el error. Aparentemente falta la conversión a hexadecimal. Cuando hago el hash en el archivo de texto, también obtengo un resultado incorrecto:

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

por lo que la transformación en una matriz de bytes hexadecimales "addressHex" seguramente le falta algo.

Actualizar:

Puedo ver la función "bytesToHex()", ¿fue este el código del enlace que proporcioné en el otro hilo? Si es así, intente volcar la salida de su java en un archivo y use hexdump para verificar. Así que puedes concentrarte en estas dos líneas (hice el comando sed más corto, sin "gato"):

$ 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

Aquí debería recibir el mismo resultado con su código Java, entonces estaría listo para continuar :-)

Gracias, edité mi código pero todavía no funciona. También he editado mi publicación para mostrar ahora el nuevo código.
mira mi actualización, eso es todo lo que puedo hacer hasta ahora...
Escuche mi respuesta en el otro hilo, el enfoque es completamente incorrecto desde el principio y puede terminar perdiendo fondos si lo usa. No deberías codificar la dirección en absoluto .