2

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?

3

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).

  • seriously, you are a magnificent human being. While it is admittedly difficult to understand this, I think I have a grasp of it, and nevertheless do have some working code that produces the same results as the tests, and hopefully thereby uses the same encoding. I will post my code in order to expose whatever flaws may exist in the logic, or optimizations that could be made to it. – doffing81 Jan 28 '17 at 0:53
  • @BrettDoffing In my opinion, you should avoid cluttering your code with tests 0 <= x < q. You probably have a method mod on your type Integer so that x.mod(q) always gives you an integer in the interval [0,q) (when x >= 0 it is simply the remainder of the division of x by q). So if x.mul(y) is the normal integer product, x.mul(y).mod(q) gives you the product in Fq 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)) when s > q/2. – Sven Williamson Jan 28 '17 at 5:40
  • Thanks for the advice. Swift uses a remainder, while my current big integer library is pretty small, with limited functionality, using remainder as well. – doffing81 Jan 28 '17 at 10:23
  • @BrettDoffing if your remainder function for big integers always returns a non-negative integer after dividing by q, then whatever (r,s) you were calculating before, take the reminders instead, and then do a last filtering to standardize before returning signature, and you should match the test vector perfectly :) – Sven Williamson Jan 28 '17 at 10:43
  • The derivation of this answer is wrong. s and -s are NOT equal mod q. The explanation is: During signature calculations we're multiplying s with a curve point G. 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), both s and -s work interchangeably in the signature. For the canonical encoding (Low S) of s we're using the smaller value of the two. – ens Feb 24 '18 at 21:02
0

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 {
        // ??
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.