Within the code libraries in Programming Bitcoin by Jimmy Track within the technique PrivateKey.signal, and within the Python package deal ecdsa.util.sigencode_der_canonize, which each assist Python 3, the checks for prime “s” worth in a signature (r, s) use floating level arithmetic :
if s > N / 2:
s = N - s
if s > order / 2:
s = order - s
respectively, the place N and “order” are the order of the elliptic curve secp256k1, and “/” is the Python 3 “true division” operator producing a floating level kind no matter the kind of the operands (eg. as described in [1] p146). The Python ecdsa package deal shouldn’t be particular to Bitcoin however in its documentation (eg. right here) it does point out this canonicalization is “mostly utilized in bitcoin”.
This causes some excessive “s” values to not be detected by these libraries and thus the canonicalization shouldn’t be carried out and the signature they produce is then thought of invalid by Bitcoin nodes. Particularly utilizing N // 2
as the precise worth of 1 lower than the “mid level” of strange prime N (the place “//” is the Python 3 “flooring division” operator which discards the rest and performs actual integer arithmetic for integer operands of arbitrary dimension (eg. [1] p135)) now we have (utilizing Python interpreter v3.8.10) :
N = order of secp256k1 generator level G =
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
N // 2 =
7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 (actual)
>>> N / 2
5.78960446186581e+76 (approximate)
>>> s = (N // 2) + 2**127
>>> s > N / 2
False
>>> s = (N // 2) + 2**128
>>> s > N / 2
True
so all of the excessive “s” values in no less than the vary [N // 2 + 1, N // 2 + 2**127]
usually are not appropriately detected.
The precise worth of N / 2
ought to be N // 2 + 0.5
, however we see it’s significantly bigger than that because of the floating level error:
>>> N/2 > N//2 + 2**127
True
>>> N/2 > N//2 + 2**128
False
Does Bitcoin work this fashion additionally and that’s the reason for floating level utilization in these libraries, to be appropriate with Bitcoin? It might appear to me higher to make use of actual integer arithmetic, even when there’s not a lot likelihood that “s” may land within the vary [N // 2 + 1, N // 2 + 2**127]
, it might appear to be higher type.
[1] Mark Lutz (2013), Studying Python fifth Version, O’Reilly