Firme un tx con valor "s bajo" usando OpenSSL

Actualmente trato de firmar un tx usando OpenSSL. Después de algunos retoques, creo que obtuve la mayor parte del tx correcto, pero Electrum se queja de mandatory-script-verify-flag-failed (Non-canonical signature: S value is unnecessarily high)que probablemente se deba a BIP62 .

¿Hay alguna manera de crear firmas adecuadas con OpenSSL, excepto intentar y esperar obtener un svalor pequeño?

El resto de mi código está en Golang y no pude encontrar un paquete adecuado para la curva ECDSA utilizada y, por lo tanto, envuelto en OpenSSL.

Respuestas (3)

Alternativamente, podría usar libsecp256k1 . Este es el código utilizado por Bitcoin Core para firmar y creará automáticamente firmas de bajo S (descargo de responsabilidad: soy el autor principal de esa biblioteca). Tal vez exista un envoltorio Go.

Si se apega a OpenSSL, es posible ajustar manualmente el valor S después de firmar. Esto es lo que solía hacer Bitcoin Core antes de la v0.10. Esto es lo que solía hacer: https://github.com/bitcoin/bitcoin/blob/v0.9.0/src/key.cpp#L204L224

Sin embargo, tal descargo de responsabilidad.

Open SSL no lo forzará, tendrá que hacerlo usted mismo. Del BIP 62:

El valor S en firmas debe estar entre 0x1 y 0x7FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0 (inclusive). Si S es demasiado alto, simplemente reemplácelo por S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S.

Fuente

La pregunta entonces es: ¿Cómo puedo establecer ese valor usando OpenSSL? No pude encontrar un parámetro para configurarlo.
@soupdiver: esos números son, no por coincidencia, el orden del grupo para secp256k1 y la mitad del orden (redondeado hacia abajo). Si tiene un EC_GROUP para secp25k1, use EC_GROUP_get[0]_order; si tiene un EC_KEY, use EC_KEY_get0_group primero. Una vez que tenga la orden BN_dup BN_rshift1 BN_cmp y BN_sub en el valor de ECDSA_SIG debería ser suficiente.
no entiendo mucho el ultimo comentario
@soupdiver no necesita 'configurarlo en OpenSSL', solo lo usa, el valor s es un componente de la firma final.
si entiendo esto Me pregunto si hay alguna forma de establecer este valor si es demasiado grande y, por lo tanto, rechazado por la red.
@soupdiver He explicado qué hacer, calcule el valor bajo como expliqué en mi pregunta y colóquelo en la firma de la transacción de bitcoin. Eso es todo lo que necesitas hacer

¿Hay alguna manera de crear firmas adecuadas con OpenSSL, excepto intentar y esperar obtener un valor de s pequeño?

Si la velocidad no es significativa, no es mala idea.

actualización: toma un poco de pseudocódigo:

while ( true )
{
  signature = createOpenSslSignature ( params );
  if ( !signature.toHex ( ).contains ( "022100" ) )
    return signature;
}
Preferiría crear firmas "adecuadas" directamente y no tener que usar la fuerza bruta :)
respuesta actualizada. esto no es fuerza bruta. y esta no es la mejor solución. pero esta es la implementación más simple :)