I have an existing system that signs an arbitrary binary blob with an ECDSA key. The output of this is an r and s value. I now need to verify this signature on another system. On this other system though we are using BouncyCastle, and would prefer to just use the byte array verify method.

Unfortunately my cryptographic mathematical skills are not up to parr and I don't know how to convert my r and s values into a byte array for the signature. How do I do this conversion?


You can choose between two signature formats. One is the most common one and has been defined by the ANS(I) X9.62 standard in ASN.1:

ECDSA-Sig-Value ::= SEQUENCE {

which is then encoded using DER TLV encoding.

For ASN.1 / DER the INTEGER values are encoded as are variable sized, signed two-complement, big endian encoded values. For instance number 255 is encoded as 00 FF (00 is required so it is not interpreted as a negative value) and 256 is encoded as 01 00.

Bouncy Castle has an ASN.1 / DER encoding / decoding facilities build in. Probably easiest is to find out where they encode their own $r$ and $s$ values to generate the usual ECDSA signature.

The other often used method is to simply concatenate the $r$ and $s$ values. In that case the signature is:

$$\operatorname{I2OSP}(r, l) \mathbin\| \operatorname{I2OSP}(s, l)$$

where $l$ is the number of octets required to encode the field size of the group. Or, put differently, $l = \big\lceil \mathrm{keysize} / 8 \big\rceil$. I2OSP has been defined, for instance, in the RSA standards and explained here. The outcome is two statically sized, unsigned, big endian numbers simply concatenated together.

This scheme is often used for smart cards, embedded computers or other schemes that require a minimum size of a signature such block chain.

  • $\begingroup$ Best ask on stackoverflow if you cannot find out how to ASN.1 encode the values. $\endgroup$ – Maarten Bodewes Jun 13 '18 at 13:51
  • 1
    $\begingroup$ If you don't want to pay for X9 (or cheat), the signature and pubkey formats are duplicated in rfc3279. For completeness, if you call directly (LWAPI) instead of going through JCA/Provider, ECDSASigner.verify takes two BigInteger directly, leaving caller to handle any encoding. $\endgroup$ – dave_thompson_085 Jun 14 '18 at 1:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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