You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.7 KiB

4 years ago
  1. '''
  2. RFC 6979:
  3. Deterministic Usage of the Digital Signature Algorithm (DSA) and
  4. Elliptic Curve Digital Signature Algorithm (ECDSA)
  5. http://tools.ietf.org/html/rfc6979
  6. Many thanks to Coda Hale for his implementation in Go language:
  7. https://github.com/codahale/rfc6979
  8. '''
  9. import hmac
  10. from binascii import hexlify
  11. from .util import number_to_string, number_to_string_crop
  12. from .six import b
  13. try:
  14. bin(0)
  15. except NameError:
  16. binmap = {"0": "0000", "1": "0001", "2": "0010", "3": "0011",
  17. "4": "0100", "5": "0101", "6": "0110", "7": "0111",
  18. "8": "1000", "9": "1001", "a": "1010", "b": "1011",
  19. "c": "1100", "d": "1101", "e": "1110", "f": "1111"}
  20. def bin(value): # for python2.5
  21. v = "".join(binmap[x] for x in "%x"%abs(value)).lstrip("0")
  22. if value < 0:
  23. return "-0b" + v
  24. return "0b" + v
  25. def bit_length(num):
  26. # http://docs.python.org/dev/library/stdtypes.html#int.bit_length
  27. s = bin(num) # binary representation: bin(-37) --> '-0b100101'
  28. s = s.lstrip('-0b') # remove leading zeros and minus sign
  29. return len(s) # len('100101') --> 6
  30. def bits2int(data, qlen):
  31. x = int(hexlify(data), 16)
  32. l = len(data) * 8
  33. if l > qlen:
  34. return x >> (l-qlen)
  35. return x
  36. def bits2octets(data, order):
  37. z1 = bits2int(data, bit_length(order))
  38. z2 = z1 - order
  39. if z2 < 0:
  40. z2 = z1
  41. return number_to_string_crop(z2, order)
  42. # https://tools.ietf.org/html/rfc6979#section-3.2
  43. def generate_k(order, secexp, hash_func, data):
  44. '''
  45. order - order of the DSA generator used in the signature
  46. secexp - secure exponent (private key) in numeric form
  47. hash_func - reference to the same hash function used for generating hash
  48. data - hash in binary form of the signing data
  49. '''
  50. qlen = bit_length(order)
  51. holen = hash_func().digest_size
  52. rolen = (qlen + 7) / 8
  53. bx = number_to_string(secexp, order) + bits2octets(data, order)
  54. # Step B
  55. v = b('\x01') * holen
  56. # Step C
  57. k = b('\x00') * holen
  58. # Step D
  59. k = hmac.new(k, v+b('\x00')+bx, hash_func).digest()
  60. # Step E
  61. v = hmac.new(k, v, hash_func).digest()
  62. # Step F
  63. k = hmac.new(k, v+b('\x01')+bx, hash_func).digest()
  64. # Step G
  65. v = hmac.new(k, v, hash_func).digest()
  66. # Step H
  67. while True:
  68. # Step H1
  69. t = b('')
  70. # Step H2
  71. while len(t) < rolen:
  72. v = hmac.new(k, v, hash_func).digest()
  73. t += v
  74. # Step H3
  75. secret = bits2int(t, qlen)
  76. if secret >= 1 and secret < order:
  77. return secret
  78. k = hmac.new(k, v+b('\x00'), hash_func).digest()
  79. v = hmac.new(k, v, hash_func).digest()