In comparing these test vectors to my own results, for tests #2 and #5, I end up with negative s values. My results show that for test #2, test_s = my_s * -1
, as an integer, yet the hexadecimal representation matches up correctly with the test, while for test #5, test_s = my_s + curve_order
. What is the proper way to handle a negative s value, or possibly, should I not be getting negative s values for these tests?
2 Answers
Let us denote curve_order
by q
. When computing a signature (r,s)
it is important to remember that r
and s
are meant to represent elements of Fq
(the field of integers modulo q
). The formula s = k^(-1)(e + rx)
is an algebraic expression in Fq
. So r
an s
are not really integers, they are integers modulo q
(so for example two integers u
and u + q
represent the same elements of Fq
). When implementing a function returning (r,s)
there is nothing wrong with internally representing these quantities as integers. But when it comes to returning values, you have to decide how you wish to encode the values r
and s
. If s
represents your implementation specific integer, do you simply want to return s
? or s + q
? or s - 3q
? All these answers are the same (simply different encodings) but there is little chance you will match a test-vector
unless you have a common encoding with it. When returning an integer s
modulo q
it is customary to encode s
as the unique integer s'
with 0 <= s' < q
equal to s mod q
.
So for example, when you say that test_s = my_s + curve_order
, you effectively agree with the test, but have not enforced the usual encoding. When you say that test_s = my_s * -1
, you genuinely disagree with the test but this is explained by 'standardization' (so make sure that you have 0 <= s < q
and if s > q/2
replace it by -s
, but make sure you encode -s
as an integer within [0,q)
, which means s
should in fact be replaced by q - s
).

- 1,524
- 10
- 24
While @SvenWilliamson has explained the answer, this is the code I have implemented get my desired results:
// As explained in @SvenWilliamson's answer - two integers s and s + q (s2) represent the same elements of Fq
let s2 = s + q
if 0 <= s && s < q {
if s > q/2 {
print((r, n - s))
} else {
print((r, s))
}
} else if 0 <= s2 && s2 < q {
if s2 > q/2 {
print((r, n - s2))
} else {
print((r, s2))
}
} else {
// ??
}
0 <= x < q
. You probably have a methodmod
on your typeInteger
so thatx.mod(q)
always gives you an integer in the interval[0,q)
(whenx >= 0
it is simply the remainder of the division ofx
byq
). So ifx.mul(y)
is the normal integer product,x.mul(y).mod(q)
gives you the product inFq
etc. So compute(r,s)
as usual and before returning it you simply standardize it by calling a method which replaces the signature(r,s)
by the (valid) signature(r, -s.mod(q))
whens > q/2
. – Sven Williamson Jan 28 '17 at 05:40s
and-s
are NOT equal mod q. The explanation is: During signature calculations we're multiplyings
with a curve pointG
. From the resulting point we're only using the x coordinate and discard the y coordinate. Because((-s)*G).x == (-(s*G)).x == (s*G).x
(negation of a point only inverts its y coord, x stays the same), boths
and-s
work interchangeably in the signature. For the canonical encoding (Low S
) ofs
we're using the smaller value of the two. – ens Feb 24 '18 at 21:02