• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tlsfuzzer / tlslite-ng / 17615324909

10 Sep 2025 01:30PM UTC coverage: 76.448% (-6.9%) from 83.378%
17615324909

Pull #556

github

web-flow
Merge 281134490 into b0f903667
Pull Request #556: ML-DSA support

4073 of 5975 branches covered (68.17%)

Branch coverage included in aggregate %.

27 of 132 new or added lines in 9 files covered. (20.45%)

928 existing lines in 40 files now uncovered.

11378 of 14236 relevant lines covered (79.92%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.69
/tlslite/utils/python_dsakey.py
1
# Author: Frantisek Krenzelok
2
"""Pure-Python RSA implementation."""
1✔
3
from ecdsa.der import encode_sequence, encode_integer,  \
1✔
4
    remove_sequence, remove_integer
5

6
from .cryptomath import getRandomNumber, getRandomPrime,    \
1✔
7
    powMod, numBits, bytesToNumber, invMod,   \
8
    secureHash, GMPY2_LOADED, gmpyLoaded
9

10
from .compat import compatHMAC
1✔
11

12
if GMPY2_LOADED:
1!
UNCOV
13
    from gmpy2 import mpz
×
14
elif gmpyLoaded:
1!
UNCOV
15
    from gmpy import mpz
×
16

17
from .dsakey import DSAKey
1✔
18

19
class Python_DSAKey(DSAKey):
1✔
20
    """
21
    Concrete implementaion of DSA object.
22
    for func docstring see tlslite/dsakey.py
23
    """
24
    def __init__(self, p=0, q=0, g=0, x=0, y=0):
1✔
25
        if gmpyLoaded or GMPY2_LOADED:
1!
UNCOV
26
            p = mpz(p)
×
UNCOV
27
            q = mpz(q)
×
UNCOV
28
            g = mpz(g)
×
UNCOV
29
            x = mpz(x)
×
UNCOV
30
            y = mpz(y)
×
31
        self.p = p
1✔
32
        self.q = q
1✔
33
        self.g = g
1✔
34
        self.private_key = x
1✔
35
        self.public_key = y
1✔
36
        if self.private_key and not self.public_key:
1✔
37
            self.public_key = powMod(g, self.private_key, p)
1✔
38
        self.key_type = "dsa"
1✔
39

40
    def __len__(self):
1✔
41
        return numBits(self.p)
1✔
42

43
    def hasPrivateKey(self):
1✔
44
        return bool(self.private_key)
1✔
45

46
    @staticmethod
1✔
47
    def generate(L, N):
48
        assert (L, N) in [(1024, 160), (2048, 224), (2048, 256), (3072, 256)]
1✔
49
        key = Python_DSAKey()
1✔
50
        (q, p) = Python_DSAKey.generate_qp(L, N)
1✔
51

52
        index = getRandomNumber(1, (p-1))
1✔
53
        g = powMod(index, int((p-1)/q), p)
1✔
54
        x = getRandomNumber(1, q-1)
1✔
55
        y = powMod(g, x, p)
1✔
56
        if gmpyLoaded or GMPY2_LOADED:
1!
UNCOV
57
            p = mpz(p)
×
UNCOV
58
            q = mpz(q)
×
UNCOV
59
            g = mpz(g)
×
UNCOV
60
            x = mpz(x)
×
UNCOV
61
            y = mpz(y)
×
62
        key.q = q
1✔
63
        key.p = p
1✔
64
        key.g = g
1✔
65
        key.private_key = x
1✔
66
        key.public_key = y
1✔
67
        return key
1✔
68

69
    @staticmethod
1✔
70
    def generate_qp(L, N):
71
        assert (L, N) in [(1024, 160), (2048, 224), (2048, 256), (3072, 256)]
1✔
72

73
        q = int(getRandomPrime(N))
1✔
74
        while True:
1✔
75
            p = int(getRandomPrime(L))
1✔
76
            if (p-1) % q:
1!
77
                break
1✔
78
        return (q, p)
1✔
79

80
    def hashAndSign(self, data, hAlg="sha1"):
1✔
81
        hashData = (secureHash(bytearray(data), hAlg))
1✔
82
        return self.sign(hashData)
1✔
83

84
    def sign(self, data, padding=None, hashAlg=None, saltLen=None):
1✔
85
        """
86
        :type data: bytearray
87
        :param data: The value which will be signed (generally a binary
88
            encoding of hash output.
89

90
        :type padding: str
91
        :param padding: Ignored, present for API compatibility with RSA
92

93
        :type hashAlg: str
94
        :param hashAlg: name of hash that was used for calculating the bytes
95

96
        :type saltLen: int
97
        :param saltLen: Ignored, present for API compatibility with RSA
98
        """
99
        N = numBits(self.q)
1✔
100
        digest_len = len(data) * 8
1✔
101
        digest = bytesToNumber(data)
1✔
102
        if N < digest_len:
1✔
103
            digest >>= digest_len - N
1✔
104

105
        k = getRandomNumber(1, (self.q-1))
1✔
106
        if gmpyLoaded or GMPY2_LOADED:
1!
UNCOV
107
            k = mpz(k)
×
UNCOV
108
            digest = mpz(digest)
×
109
        r = powMod(self.g, k, self.p) % self.q
1✔
110
        s = invMod(k, self.q) * (digest + self.private_key * r) % self.q
1✔
111

112
        return encode_sequence(encode_integer(r), encode_integer(s))
1✔
113

114
    def verify(self, signature, hashData, padding=None, hashAlg=None,
1✔
115
               saltLen=None):
116
        """Verify the passed-in bytes with the signature.
117

118
        This verifies a DSA signature on the passed-in data.
119

120
        :type signature: bytearray
121
        :param signature: The signature.
122

123
        :type hashData: bytearray
124
        :param hashData: The value which will be verified.
125

126
        :type padding: str
127
        :param padding: Ignored, present for API compatibility with RSA
128

129
        :type hashAlg: str
130
        :param hashAlg: Ignored, present for API compatibility with RSA
131

132
        :type saltLen: str
133
        :param saltLen: Ignored, present for API compatibility with RSA
134

135
        :rtype: bool
136
        :returns: Whether the signature matches the passed-in data.
137
        """
138
        N = numBits(self.q)
1✔
139
        digest_len = len(hashData) * 8
1✔
140
        digest = bytesToNumber(hashData)
1✔
141

142
        if N < digest_len:
1✔
143
            digest >>= digest_len - N
1✔
144

145
        signature = compatHMAC(signature)
1✔
146

147
        # get r, s keys
148
        if not signature:
1!
149
            return False
×
150
        body, rest = remove_sequence(signature)
1✔
151
        if rest:
1!
152
            return False
×
153
        r, rest = remove_integer(body)
1✔
154
        s, rest = remove_integer(rest)
1✔
155
        if rest:
1✔
156
            return False
1✔
157

158
        if gmpyLoaded or GMPY2_LOADED:
1!
UNCOV
159
            r = mpz(r)
×
UNCOV
160
            s = mpz(s)
×
161

162
        # check the signature
163
        if 0 < r < self.q and 0 < s < self.q:
1!
164
            w = invMod(s, self.q)
1✔
165
            u1 = (digest * w) % self.q
1✔
166
            u2 = (r * w) % self.q
1✔
167
            v = ((powMod(self.g, u1, self.p) * \
1✔
168
                  powMod(self.public_key, u2, self.p)) % self.p) % self.q
169
            return r == v
1✔
170
        return False
×
171

172
    def hashAndVerify(self, signature, data, hAlg="sha1"):
1✔
173
        digest = secureHash(bytearray(data), hAlg)
1✔
174
        return self.verify(signature, digest)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc