Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/ecdsa/rfc6979.py: 18%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

49 statements  

1""" 

2RFC 6979: 

3 Deterministic Usage of the Digital Signature Algorithm (DSA) and 

4 Elliptic Curve Digital Signature Algorithm (ECDSA) 

5 

6 http://tools.ietf.org/html/rfc6979 

7 

8Many thanks to Coda Hale for his implementation in Go language: 

9 https://github.com/codahale/rfc6979 

10""" 

11 

12import hmac 

13from binascii import hexlify 

14from .util import number_to_string, number_to_string_crop, bit_length 

15from ._compat import hmac_compat 

16 

17 

18# bit_length was defined in this module previously so keep it for backwards 

19# compatibility, will need to deprecate and remove it later 

20__all__ = ["bit_length", "bits2int", "bits2octets", "generate_k"] 

21 

22 

23def bits2int(data, qlen): 

24 x = int(hexlify(data), 16) 

25 l = len(data) * 8 

26 

27 if l > qlen: 

28 return x >> (l - qlen) 

29 return x 

30 

31 

32def bits2octets(data, order): 

33 z1 = bits2int(data, bit_length(order)) 

34 z2 = z1 - order 

35 

36 if z2 < 0: 

37 z2 = z1 

38 

39 return number_to_string_crop(z2, order) 

40 

41 

42# https://tools.ietf.org/html/rfc6979#section-3.2 

43def generate_k(order, secexp, hash_func, data, retry_gen=0, extra_entropy=b""): 

44 """ 

45 Generate the ``k`` value - the nonce for DSA. 

46 

47 :param int order: order of the DSA generator used in the signature 

48 :param int secexp: secure exponent (private key) in numeric form 

49 :param hash_func: reference to the same hash function used for generating 

50 hash, like :py:class:`hashlib.sha1` 

51 :param bytes data: hash in binary form of the signing data 

52 :param int retry_gen: how many good 'k' values to skip before returning 

53 :param bytes extra_entropy: additional added data in binary form as per 

54 section-3.6 of rfc6979 

55 :rtype: int 

56 """ 

57 

58 qlen = bit_length(order) 

59 holen = hash_func().digest_size 

60 rolen = (qlen + 7) // 8 

61 bx = ( 

62 hmac_compat(number_to_string(secexp, order)), 

63 hmac_compat(bits2octets(data, order)), 

64 hmac_compat(extra_entropy), 

65 ) 

66 

67 # Step B 

68 v = b"\x01" * holen 

69 

70 # Step C 

71 k = b"\x00" * holen 

72 

73 # Step D 

74 

75 k = hmac.new(k, digestmod=hash_func) 

76 k.update(v + b"\x00") 

77 for i in bx: 

78 k.update(i) 

79 k = k.digest() 

80 

81 # Step E 

82 v = hmac.new(k, v, hash_func).digest() 

83 

84 # Step F 

85 k = hmac.new(k, digestmod=hash_func) 

86 k.update(v + b"\x01") 

87 for i in bx: 

88 k.update(i) 

89 k = k.digest() 

90 

91 # Step G 

92 v = hmac.new(k, v, hash_func).digest() 

93 

94 # Step H 

95 while True: 

96 # Step H1 

97 t = b"" 

98 

99 # Step H2 

100 while len(t) < rolen: 

101 v = hmac.new(k, v, hash_func).digest() 

102 t += v 

103 

104 # Step H3 

105 secret = bits2int(t, qlen) 

106 

107 if 1 <= secret < order: 

108 if retry_gen <= 0: 

109 return secret 

110 retry_gen -= 1 

111 

112 k = hmac.new(k, v + b"\x00", hash_func).digest() 

113 v = hmac.new(k, v, hash_func).digest()