I currently try to sign a tx using OpenSSL. After some tinkering I think I got most of the tx right but Electrum complains with mandatory-script-verify-flag-failed (Non-canonical signature: S value is unnecessarily high) which is probably because of BIP62.

Is there a way to create proper signatures with OpenSSL except trying and hoping to get a small s value?

The rest of my code is in Golang and I couldn't find a proper packages for the used ECDSA curve and so wrapped around OpenSSL.

3 Answers 3


Alternatively, you could use libsecp256k1. This is the code used by Bitcoin Core for signing, and will automatically create low-S signatures (disclaimer: I'm the main author of that library). Perhaps a Go wrapper exists.

If you stick to OpenSSL, it is possible to manually adjust the S value after signing. This is what Bitcoin Core used to do before v0.10. Here is what it used to do: https://github.com/bitcoin/bitcoin/blob/v0.9.0/src/key.cpp#L204L224

  • Such a disclaimer though.
    – sr_gi
    Sep 22, 2017 at 18:42

Open SSL won't force it, you will have to do it yourself. From BIP 62:

The value S in signatures must be between 0x1 and 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0 (inclusive). If S is too high, simply replace it by S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S.


  • The question then is: How can I set that s value using OpenSSL? I couldn't find a parameter to set it
    – soupdiver
    Sep 22, 2017 at 6:57
  • @soupdiver: those numbers are, not coincidentally, the order of the group for secp256k1 and one-half the order (rounded down). If you have an EC_GROUP for secp25k1 use EC_GROUP_get[0]_order; if you have an EC_KEY use EC_KEY_get0_group first. Once you have the order BN_dup BN_rshift1 BN_cmp and BN_sub on the value from the ECDSA_SIG should be sufficient. Sep 22, 2017 at 11:45
  • I don't really understand the last comment
    – soupdiver
    Sep 22, 2017 at 11:46
  • @soupdiver you don't need to 'set it in OpenSSL', you just use it, the s value is a component of the final signature. Sep 22, 2017 at 11:52
  • yeah I understand this. I'm wondering if there is a way to set this value if it's too big and therefor rejected by the network
    – soupdiver
    Sep 22, 2017 at 13:02

Is there a way to create proper signatures with OpenSSL except trying and hoping to get a small s value?

If the speed is not significant - this is not bad idea.

update: take some pseudocode:

while ( true )
  signature = createOpenSslSignature ( params );
  if ( !signature.toHex ( ).contains ( "022100" ) )
    return signature;
  • I would prefer to create "proper" signatures directly and not having to brute force it :)
    – soupdiver
    Sep 22, 2017 at 6:58
  • 1
    answer updated. this in not brute-forcing. and this is not best solution. but this is simplest implementation :)
    – amaclin
    Sep 22, 2017 at 16:59

Your Answer

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

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