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
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
1"""
2RFC 6979:
3 Deterministic Usage of the Digital Signature Algorithm (DSA) and
4 Elliptic Curve Digital Signature Algorithm (ECDSA)
6 http://tools.ietf.org/html/rfc6979
8Many thanks to Coda Hale for his implementation in Go language:
9 https://github.com/codahale/rfc6979
10"""
12import hmac
13from binascii import hexlify
14from .util import number_to_string, number_to_string_crop, bit_length
15from ._compat import hmac_compat
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"]
23def bits2int(data, qlen):
24 x = int(hexlify(data), 16)
25 l = len(data) * 8
27 if l > qlen:
28 return x >> (l - qlen)
29 return x
32def bits2octets(data, order):
33 z1 = bits2int(data, bit_length(order))
34 z2 = z1 - order
36 if z2 < 0:
37 z2 = z1
39 return number_to_string_crop(z2, order)
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.
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 """
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 )
67 # Step B
68 v = b"\x01" * holen
70 # Step C
71 k = b"\x00" * holen
73 # Step D
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()
81 # Step E
82 v = hmac.new(k, v, hash_func).digest()
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()
91 # Step G
92 v = hmac.new(k, v, hash_func).digest()
94 # Step H
95 while True:
96 # Step H1
97 t = b""
99 # Step H2
100 while len(t) < rolen:
101 v = hmac.new(k, v, hash_func).digest()
102 t += v
104 # Step H3
105 secret = bits2int(t, qlen)
107 if 1 <= secret < order:
108 if retry_gen <= 0:
109 return secret
110 retry_gen -= 1
112 k = hmac.new(k, v + b"\x00", hash_func).digest()
113 v = hmac.new(k, v, hash_func).digest()