es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo firmar sin conexión una transacción de Tron en Ruby?

Estoy tratando de firmar sin conexión una transacción de Tron en Ruby.

TronGrid tiene un punto final para firmar transacciones, pero requieren que les envíen la clave privada de la cuenta para hacerlo, lo cual representa un riesgo potencial, así que me gustaría firmar la transacción localmente para evitar que el valor de la clave privada salga del servidor.

Específicamente, estoy tratando de convertir este método de JavaScript a Ruby: https://github.com/tronprotocol/tronweb/blob/master/src/utils/crypto.js#L218

He intentado hacer esto usando tanto OpenSSL como una gema (https://github.com/rubycoco/blockchain/elliptic) sin mucho éxito.

Esto es lo que he logrado hasta ahora:

bn = OpenSSL::BN.new(hex_private_key, 16)
ec = OpenSSL::PKey::EC.new('secp256k1')
ec.private_key = bn
ec.dsa_sign_asn1(transaction_id).unpack1('H*')

y

bn = OpenSSL::BN.new(hex_private_key, 16)
private_key = EC::PrivateKey.new(bn.to_i)
signature = private_key.sign(transaction_id)

Este último me da la “r” y la “s” que luego se utilizan en la función de JavaScript (aunque no coincidirían con lo que obtendría en JS), y no estoy seguro de dónde podría obtener ese “recoveryParam”.

Y el primero no me devuelve la firma que esperaba.

Estoy algo perdido en cómo encontrar una manera de firmar esas transacciones.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en Ruby, encriptación, criptografía, Tron y secp256k1, hay algunas opciones que puedes probar para firmar sin conexión una transacción de Tron en Ruby sin enviar la clave privada de la cuenta.

    Una opción es utilizar la biblioteca ruby-tron, la cual proporciona un conjunto de métodos para interactuar con la red de Tron, incluyendo firmar transacciones. Puedes instalarla utilizando el siguiente comando:

    gem install ruby-tron
    

    Para firmar una transacción utilizando esta biblioteca, puedes usar el siguiente fragmento de código:

    require 'ruby-tron'
    
    # Crear una instancia del cliente de Tron
    client = Tron::Client.new
    
    # Establecer la clave privada (en formato hexadecimal)
    private_key = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
    
    # Crear una instancia de la clave de Tron
    key = Tron::Key.new(private_key)
    
    # Establecer los datos de la transacción (en formato de hash)
    transaction_data = {
      from: 'TU_DIRECCIÓN',
      to: 'DIRECCIÓN_DEL_RECEPTOR',
      value: 10_000_000
    }
    
    # Firmar la transacción utilizando la clave
    signed_transaction = key.sign(transaction_data)
    
    # Transmitir la transacción firmada a la red de Tron
    client.broadcast_transaction(signed_transaction)
    

    Otra opción es utilizar la biblioteca secp256k1 en combinación con la biblioteca OpenSSL. A continuación, se muestra un ejemplo de fragmento de código que demuestra cómo hacer esto:

    require 'secp256k1'
    require 'openssl'
    
    # Establecer la clave privada (en formato hexadecimal)
    private_key = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
    
    # Establecer los datos de la transacción (en formato de hash)
    transaction_data = 'e8646d693d2598f9b22a589c7d1a390f8236b84c62b521365e7d1af2c2f3159f'
    
    # Convertir la clave privada a una instancia de BN
    private_key_bn = OpenSSL::BN.new(private_key, 16)
    
    # Crear una instancia de EC con la curva secp256k1
    ec = OpenSSL::PKey::EC.new('secp256k1')
    
    # Establecer la clave privada en la instancia de EC
    ec.private_key = private_key_bn
    
    # Generar la firma codificada en DER
    signature_der = ec.dsa_sign_asn1([transaction_data].pack('H*'))
    
    # Extraer los valores R y S de la firma
    r = OpenSSL::BN.new(signature_der[4..36], 2).to_i
    s = OpenSSL::BN.new(signature_der[39..71], 2).to_i
    
    # Calcular el ID de recuperación (0 o 1)
    recovery_id = 0 + (ec.dsa_verify_asn1([transaction_data].pack('H*'), signature_der) ? ec.group.order : 0)
    
    # Combinar los valores de R, S y ID de recuperación en una única firma
    signature = (r << 1) + recovery_id + (s << (32 * 8 - 1 - s.to_s(2).length))
    
    # Convertir la firma a formato hexadecimal
    signature_hex = signature.to_s(16)
    
    # Imprimir la firma
    puts signature_hex
    

    Espero que estas soluciones te ayuden a firmar tus transacciones de Tron sin conexión y de forma segura en Ruby.

Comments are closed.