Cómo firmar una transacción sin procesar con una clave privada y un hash SHA (en Java)

He seguido las instrucciones aquí para crear mi propia transacción de bitcoin.

Se requiere un ejemplo de canje de una transacción sin procesar paso a paso

Actualmente, mi código puede crear una transacción y calcular el hash SHA, pero tengo dificultades para firmarlo con ECDSA.

He escrito un código para hacerlo usando bitcoinj pero no funciona. Necesito ayuda para firmar una transacción usando una biblioteca Java o una API.

Esto es lo que tengo hasta ahora. Cualquier ayuda será muy apreciada :).

import org.apache.commons.codec.binary.Hex;
import org.bitcoinj.core.*;
import org.bitcoinj.core.ECKey.*;

public class Test3 {
    public static void main(String[] args) {

        //Given private key and SHA 256 Hash, sign a transaction

        String shaHash = "15953935a135031bfec37d36a9d662aea43e1deb0ea463d6932ac6e537cb3e81";
        String privateKey = "private key for the address";      

        byte[] priv = Base58.decode(privateKey);
        // Generate ecsda key    
        ECKey ecdsa = ECKey.fromPrivate(priv);      
        Sha256Hash hash = new Sha256Hash(shaHash);
        // Sign the transaction
        ECDSASignature sig = ecdsa.sign(hash);
        byte[] res = sig.encodeToDER();
        String res2 = Hex.encodeHexString(res);

        System.out.println(res2);



    }
}
Así que creo que el problema puede ser que la clave privada esté en un formato WIF que necesito convertir en una clave privada ECDSA, pero no estoy seguro de cómo hacerlo.

Respuestas (1)

Esta respuesta no intenta firmar una transacción, sino que simplemente se enfoca en llamar con éxito al signmétodo de la ECKeyclase, es decir, hacer que su código funcione . Todavía no estoy familiarizado con la TransactionAPI de bitcoinj, por lo que no puedo ir más allá. Su publicación sugiere que su clave privada se proporciona como WiFuna suposición. La principal dificultad es instanciar un ECKeyobjeto desde el WiFcual he agregado a su código. También he reemplazado el obsoleto new Sha256Hash(...)por el wrapmétodo. Estoy usando una función diferente para codificar como una cadena hexadecimal, pero puedes cambiar eso fácilmente. El código se compila con éxito en las ejecuciones.

import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Base58;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.DumpedPrivateKey;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ECKey.ECDSASignature;
import javax.xml.bind.DatatypeConverter;

public class Test {

  public static void main(String[] args){

    // message (hash) to be signed with private key
    String msg = "15953935a135031bfec37d36a9d662aea43e1deb0ea463d6932ac6e537cb3e81";

    // an example of WiF for private key (taken from 'Mastering Bitcoin')
    String wif ="KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ";      

    // creating a key object from WiF
    DumpedPrivateKey dpk = DumpedPrivateKey.fromBase58(null, wif);
    ECKey key = dpk.getKey();

    // checking our key object
    NetworkParameters main =  MainNetParams.get();
    String check = key.getPrivateKeyAsWiF(main);
    System.out.println(wif.equals(check));  // true

    // creating Sha object from string
    Sha256Hash hash = Sha256Hash.wrap(msg);

    // creating signature
    ECDSASignature sig = key.sign(hash);

    // encoding
    byte[] res = sig.encodeToDER();

    // converting to hex
    String hex = DatatypeConverter.printHexBinary(res); 

    System.out.println(hex);  // 304502210081B528....

  }
}
Perfecto, muchas gracias por tu ayuda! Mi código ahora está funcionando.