0

I see that my ASN1/DER signature contains the individual r and s values, is there a way to derive the generic 64byte signature?

edit: Ive looked through the DER/ASN1 spec, seems that what Im looking for is simply s appended to r. BUT both r and s can possibly have lengths of 32 or 33. so its possible for my raw EC signature to be 66 bytes long, which completely breaks the application I use now.

But Ive noticed that whenever the DER specifies eother r or s to be 33 bytes long, the very first byte is 0x00. I suppose I can simply throw that out and then have 64 bytes?

1

simply s appended to r.

It is not that simple. DER encoding uses a Tag-Length-Value format. In this format every "value" (like a number, string,...) that you want to encode starts with its own special "tag", a single byte that indicates the type (eg. Boolean is 0x01, integer is 0x02, sequence is 0x03) followed by a number that indicates the length of the "value" called "length" (eg. 32 is 0x20, 130 is 0x8182) and finally the "value" itself.

Since Signatures we are using in bitcoin are 2 integers we use a sequence of integers so the format turns into SequenceTag+TotalLength+SequenceValue where the sequence is the 2 integers each formatted the same: IntegerTag+IntegerLength+IntegerValue.

Now that we covered the format let's look at the integers. You have to remember that DER encoding is designed to encode a ton of things including both negative and positive numbers. One way of including sign of a number in its byte array representation is to use its most significant bit as the "sign bit". So when we have a byte array starting with 0b1000_0000 (128 decimal or 0x80 hex) and any number above that, that is a negative number. As a result when we have a positive number that has its most significant bit set, 1 zero byte is appended to it to make sure it is positive.

r and s can possibly have lengths of 32 or 33. so its possible for my raw EC signature to be 66 bytes long, which completely breaks the application I use now.

The application you use must not hard code values like 32, 33 or 66,... at all because these are maximum lengths not the only possible ones. for instance both r and s can be smaller like 20 bytes so your signature can end up being like this: 30380214<20bytes>0220<32bytes> a total of 58 bytes.

1

You are on the right track. R and S data bytes typically encode 256-bit values (32 bytes). However, integers in DER are signed, which means that if their highest bit is set, they are interpreted as negative. For that reason, if the R or S value being encoded has their first byte >= 0x80, it would mean a negative number, and hence a null byte is appended taking the length to 33 bytes. So to encode the signature to 64 bytes, just take the last 32 bytes each of the R and S values.

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.