Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a DER formatted ECDSA signature from raw r and s

I have a raw ECDSA signature: R and S values. I need a DER-encoded version of the signature. Is there a straightforward way to do this in openssl using the c interface?

My current attempt is to use i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp) to populate an ECDSA_SIG*. The call returns non-zero but the target buffer doesn't seem to be changed.

I'm intiailly filling my ECDSA_SIG wtih r and s values. I don't see any errors. The man page says r and s should be allocated when I call ECDSA_SIG_new

ECDSA_SIG* ec_sig = ECDSA_SIG_new();

if (NULL == BN_bin2bn(sig, 32, (ec_sig->r))) {
  dumpOpenSslErrors();
 }
DBG("post r  :%s\n", BN_bn2hex(ec_sig->r));

if (NULL == BN_bin2bn(sig + 32, 32, (ec_sig->s))) {
  dumpOpenSslErrors();
 }
DBG("post s  :%s\n", BN_bn2hex(ec_sig->s));

S and R are now set:

post r :397116930C282D1FCB71166A2D06728120CF2EE5CF6CCD4E2D822E8E0AE24A30 post s :9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9

now to make the encoded signature.

int sig_size = i2d_ECDSA_SIG(ec_sig, NULL);
if (sig_size > 255) {
  DBG("signature is too large wants %d\n", sig_size);
 }
DBG("post i2d:%s\n", BN_bn2hex(ec_sig->s));

s hasn't changed:

post i2d:9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9

At this point I have more than enough bytes ready and I set the target to all 6s so it's easy to see what changes.

unsigned char* sig_bytes = new unsigned char[256];
memset(sig_bytes, 6, 256);

sig_size = i2d_ECDSA_SIG(ec_sig, (&sig_bytes));
DBG("New size %d\n", sig_size);
DBG("post i2d:%s\n", BN_bn2hex(ec_sig->s));

hexDump("Sig ", (const byte*)sig_bytes, sig_size);

The new size is 71 New size 71 and s iis stiill the same:

  `post i2d:9E997D4718A7603942834FBDD22A4B856FC4083704EDE62033CF1A77CB9822A9`

The hex dump is all 6s.

  --Sig --  
  0x06:   0x06:   0x06:   0x06:   0x06:   0x06:   0x06:   0x06: 
  0x06:   ...

The dump is still all 6s even though the call didn't return 0. What am I missing tying to DER encode this raw signature?

like image 210
Paul Rubel Avatar asked Jul 13 '15 18:07

Paul Rubel


People also ask

What is R and S in Ecdsa signature?

The signature of ECDSA consists of a combination of R and S , where R is a value that is dependent of random parameter k which is in turn input into the ECDSA algorithm. S in turn depends on that value. If R would be a static value then it would allow an attacker to calculate the private key (!).

What is Der signature?

The standard for serializing signatures is called DER format. DER stands for Distinguished Encoding Rules and was used by Satoshi to create Bitcoin. This was most likely because the standard was already defined in 2008 and it was easy enough to adopt, rather than creating a new standard.

How do I verify Ecdsa signature?

The algorithm to verify a ECDSA signature takes as input the signed message msg + the signature {r, s} produced from the signing algorithm + the public key pubKey, corresponding to the signer's private key. The output is boolean value: valid or invalid signature.


1 Answers

i2d_ECDSA_SIG modifies its second argument, increasing it by the size of the signature. From ecdsa.h:

/** DER encode content of ECDSA_SIG object (note: this function modifies *pp
 *  (*pp += length of the DER encoded signature)).
 *  \param  sig  pointer to the ECDSA_SIG object
 *  \param  pp   pointer to a unsigned char pointer for the output or NULL
 *  \return the length of the DER encoded ECDSA_SIG object or 0
 */
int   i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);

So you need to keep track of the original value of sig_bytes when you call i2d_ECDSA_SIG:

int sig_size = i2d_ECDSA_SIG(ec_sig, NULL);
unsigned char *sig_bytes = malloc(sig_size);
unsigned char *p;
memset(sig_bytes, 6, sig_size);

p = sig_bytes;
new_sig_size = i2d_ECDSA_SIG(_sig, &p);

// The value of p is now sig_bytes + sig_size, and the signature resides at sig_bytes

Output:

30 45 02 20 39 71 16 93 0C 28 2D 1F CB 71 16 6A
2D 06 72 81 20 CF 2E E5 CF 6C CD 4E 2D 82 2E 8E
0A E2 4A 30 02 21 00 9E 99 7D 47 18 A7 60 39 42
83 4F BD D2 2A 4B 85 6F C4 08 37 04 ED E6 20 33
CF 1A 77 CB 98 22 A9
like image 184
dbush Avatar answered Oct 08 '22 15:10

dbush