|
1 | 1 | from __future__ import print_function |
2 | | -import random |
| 2 | +import sys |
| 3 | +import hypothesis.strategies as st |
| 4 | +from hypothesis import given, settings, note |
3 | 5 | from .ecdsa import Private_key, Public_key, Signature, \ |
4 | | - curve_192, generator_192, digest_integer, ellipticcurve, point_is_valid |
| 6 | + curve_192, generator_192, digest_integer, ellipticcurve, point_is_valid, \ |
| 7 | + generator_224, generator_256, generator_384, generator_521, \ |
| 8 | + generator_secp256k1 |
| 9 | + |
| 10 | + |
| 11 | +HYP_SETTINGS = {} |
| 12 | +# old hypothesis doesn't have the "deadline" setting |
| 13 | +if sys.version_info > (2, 7): |
| 14 | + # SEC521p is slow, allow long execution for it |
| 15 | + HYP_SETTINGS["deadline"] = 5000 |
5 | 16 |
|
6 | 17 |
|
7 | 18 | def test_ecdsa(): |
@@ -293,38 +304,45 @@ def test_pk_recovery(Msg, R, S, Qx, Qy): |
293 | 304 | S = 0x984c2db99827576c0a41a5da41e07d8cc768bc82f18c9da9 |
294 | 305 | test_signature_validity(Msg, Qx, Qy, R, S, False) |
295 | 306 |
|
296 | | - print("Testing the example code:") |
297 | | - |
298 | | - # Building a public/private key pair from the NIST Curve P-192: |
299 | | - |
300 | | - g = generator_192 |
301 | | - n = g.order() |
302 | | - |
303 | | - # (random.SystemRandom is supposed to provide |
304 | | - # crypto-quality random numbers, but as Debian recently |
305 | | - # illustrated, a systems programmer can accidentally |
306 | | - # demolish this security, so in serious applications |
307 | | - # further precautions are appropriate.) |
308 | | - |
309 | | - randrange = random.SystemRandom().randrange |
310 | | - |
311 | | - secret = randrange(1, n) |
312 | | - pubkey = Public_key(g, g * secret) |
313 | | - privkey = Private_key(pubkey, secret) |
314 | 307 |
|
315 | | - # Signing a hash value: |
316 | | - |
317 | | - hash = randrange(1, n) |
318 | | - signature = privkey.sign(hash, randrange(1, n)) |
319 | | - |
320 | | - # Verifying a signature for a hash value: |
321 | | - |
322 | | - if pubkey.verifies(hash, signature): |
323 | | - print("Demo verification succeeded.") |
324 | | - else: |
325 | | - raise TestFailure("*** Demo verification failed.") |
326 | | - |
327 | | - if pubkey.verifies(hash - 1, signature): |
328 | | - raise TestFailure("**** Demo verification failed to reject tampered hash.") |
329 | | - else: |
330 | | - print("Demo verification correctly rejected tampered hash.") |
| 308 | +@st.composite |
| 309 | +def st_random_gen_key_msg_nonce(draw): |
| 310 | + """Hypothesis strategy for test_sig_verify().""" |
| 311 | + name_gen = { |
| 312 | + "generator_192": generator_192, |
| 313 | + "generator_224": generator_224, |
| 314 | + "generator_256": generator_256, |
| 315 | + "generator_secp256k1": generator_secp256k1, |
| 316 | + "generator_384": generator_384, |
| 317 | + "generator_521": generator_521} |
| 318 | + name = draw(st.sampled_from(sorted(name_gen.keys()))) |
| 319 | + note("Generator used: {0}".format(name)) |
| 320 | + generator = name_gen[name] |
| 321 | + order = generator.order() |
| 322 | + |
| 323 | + key = draw(st.integers(min_value=1, max_value=order)) |
| 324 | + msg = draw(st.integers(min_value=1, max_value=order)) |
| 325 | + nonce = draw(st.integers(min_value=1, max_value=order+1) | |
| 326 | + st.integers(min_value=order>>1, max_value=order)) |
| 327 | + return generator, key, msg, nonce |
| 328 | + |
| 329 | + |
| 330 | +SIG_VER_SETTINGS = dict(HYP_SETTINGS) |
| 331 | +SIG_VER_SETTINGS["max_examples"] = 10 |
| 332 | +@settings(**SIG_VER_SETTINGS) |
| 333 | +@given(st_random_gen_key_msg_nonce()) |
| 334 | +def test_sig_verify(args): |
| 335 | + """ |
| 336 | + Check if signing and verification works for arbitrary messages and |
| 337 | + that signatures for other messages are rejected. |
| 338 | + """ |
| 339 | + generator, sec_mult, msg, nonce = args |
| 340 | + |
| 341 | + pubkey = Public_key(generator, generator * sec_mult) |
| 342 | + privkey = Private_key(pubkey, sec_mult) |
| 343 | + |
| 344 | + signature = privkey.sign(msg, nonce) |
| 345 | + |
| 346 | + assert pubkey.verifies(msg, signature) |
| 347 | + |
| 348 | + assert not pubkey.verifies(msg - 1, signature) |
0 commit comments