Skip to content

Instantly share code, notes, and snippets.

@thejohnfreeman
Last active April 9, 2020 19:28
Show Gist options
  • Save thejohnfreeman/1748a3910268f3c02b36f8409b7f6233 to your computer and use it in GitHub Desktop.
Save thejohnfreeman/1748a3910268f3c02b36f8409b7f6233 to your computer and use it in GitHub Desktop.
GROUP_ORDER = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'
// Divide by two and round up = shift right 1 bit and add 1.
HALF_GROUP_ORDER = '7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A1'
function isFullyCanonical(signatureDer) {
s = signatureDer.slice(-32)
// A lexicographical compare between big-endian hex strings yields the same ordering
// as a comparision of the unsigned integers they represent.
return s < HALF_GROUP_ORDER
}
signatureDer = '30440220...'
isFullyCanonical(signatureDer)
@thejohnfreeman
Copy link
Author

thejohnfreeman commented Apr 9, 2020

Yes. Let me break down the DER encoding of the signature:

  • 3044: sequence of (44 in base 16) = 68 bytes
  • 0220: integer of (20 in base 16) = 32 bytes (if a positive integer has 1 for the most-significant bit of its most-significant byte, it is prefixed with a zero byte 00)
  • ... 32 bytes of r ...
  • 0220: integer of (20 in base 16) = 32 bytes
  • ... 32 bytes of s ...

@shaelilwang
Copy link

Just so I understand -- for this example, s is after 0220. s in this case is 3CD9...F4F3, and a canonical sig because less than HALF_GROUP_ORDER? Should it be signatureDer.slice(-64) instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment