Difference between DER encoded signatures in JavaScript, Java, and C++ I'm trying to understand the DER-encoded signatures for the secp256k1 (ECDSA) curve better, so I have the following data array: 000102030405060708090a, which is a hex-encoded version of an array containing the numbers 0 to 10. 

Also, I have the signed it with the following private key: fabb33890c65b059996546344a7e8c5adc09167fe9e09ddd6cbcac5a84790f7f, and corresponding public key: 
{x: '1b6ae9e65a66ee3de4d04d479a806fc0f3266a0aa12e0c03f8c0f31e1bbf98fd', y: 'abc78ffe0a5381472098738d0d14b0c0f1bdda149ccf5866a4b523b8bcc9fba6'}

In Java, I get the following DER signature: 3045022065A67F8FF9CB5EA8BE899E94CB338FE09E2E596BC047D936FC2B96DC013B5DFC022100BE123D3F143AF91E4551AAFAE49C9187F64E323F5660D6C6198A9446C3F818A1, with the following code:

BigInteger priv = new BigInteger("fabb33890c65b059996546344a7e8c5adc09167fe9e09ddd6cbcac5a84790f7f", 16);
PrivateKey privateKey = getPrivateKeyFromECBigIntAndCurve(priv, "secp256k1");
byte[] data = DatatypeConverter.parseHexBinary("000102030405060708090a");

Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signed = signature.sign();
DatatypeConverter.printHexBinary(signed);


However, in JavaScript using the Elliptic or any other library, I get the following signature: 304502210099d0c79559ab4e5484a116e858ce7f59b91050cf4931a925438d876fad500ed2022067fd6e1012ed7ebcd772546bd5bf130f8af1b8282c5395f4a7164bc55255975c, using the following code:

const ec = new EC('secp256k1');
const key = ec.keyFromPrivate(privateKeyHex, 'hex');
const signature = key.sign(msg, { canonical: true });
signature.toDER('hex');


In C++, using the library botan and with the code beneath I get the following signature: 304402201EE0F965F837E7C0874C99B6C2B8C7475C7DD748AC9521B40A3BEDDB58A7722A02205125EFB0E36F6ABB59A97AFAB5D2795BCBA3D1A181D97D20587B6DC2CED5299A.

Botan::AutoSeeded_RNG rng;
Botan::PK_Signer signer(*privateKey, rng, "EMSA1(SHA-256)", Botan::DER_SEQUENCE);
signer.sign_message(data, rng);


Is there a reason for these differences, because signing it in one language and verifying it in another language will give an error. Also, if possible, how would I get the result of Java using JavaScript? My guess is that it has something to do with the encoding.

Thanks in advance!
Is there a reason for these differences


You do realize that ECDSA is randomized [1], that is, signing the same message twice with the same private key will generate two different signatures.  This is normal, and not due to you using three different ECDSA implementations.

All three signatures are DER-encodings of 'a list of two integers, both of which are 32 byte positive values', which is the expected encoding of an ECDSA signature.  Note: in DER, if you encode a value between $2^{255}$ and $2^{256}-1$, that uses an additional byte.  That happens about half the time (for both integers) in an ECDSA secp256k1signature, and accounts for the slight length differences in your examples.


  because signing it in one language and verifying it in another language will give an error.


Have you tried it?


  I'm trying to understand the DER-encoded signatures for the secp256k1 (ECDSA) curve better,


Ok, here is the break down (using the first signature as an example)

30 - This is a magic number that says "this is a list of objects"

45 - This signifies that the list of objects takes up 45 hex (69 decimal) bytes (not counting the magic number or the length field itself)

02 - This is a magic number that says "this is an integer"

20 - This says that this integer takes up 20 hex (32 decimal) bytes

65A67F8FF9CB5EA8BE899E94CB338FE09E2E596BC047D936FC2B96DC013B5DFC - These 32 bytes are the integer (in bigendian notation)

02 - This is a magic number that says "this is an integer"

21 - This says that this integer takes up 21 hex (33 decimal) bytes.  This is one byte longer because DER states that "if the top bit of an integer is a 1, the integer is negative", and so to encode a positive integer with a msbit of 1, we need to prepend a 00 byte (increasing its length by 1)

00BE123D3F143AF91E4551AAFAE49C9187F64E323F5660D6C6198A9446C3F818A1 - These 33 bytes are the integer (again, in bigendian notation).

The two encoded integers are the r, s values of the ECDSA signature



[1]: actually, there are deterministic versions of ECDSA, where the message and the private key are used to generate the 'randomness' used to generate the ECDSA signature - I assume that's not in play here, or at least, your three examples don't use the exact same method of doing determinism.