• 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

95.38
/tlslite/utils/python_tripledes.py
1
#################################################
2
#               Documentation                   #
3
#################################################
4

5
# Author:   Todd Whiteman
6
# Date:     16th March, 2009
7
# Verion:   2.0.0
8
# License:  Public Domain - free to do as you wish
9
# Homepage: http://twhiteman.netfirms.com/Des.html
10
#
11
# Modified by: Adam Varga, 2018
12
#
13
# A pure python implementation of the DES and Triple DES
14
# encryption algorithms using CBC mode. Triple DES class is
15
# implemented by utilising the DES base. Triple DES is
16
# DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.
17

18
"""
1✔
19
Class initialization
20
--------------------
21
pyDes.Des(key, iv)
22
pyDes.Python_TripleDES(key, iv)
23

24
key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes
25
       for Triple DES
26
iv  -> Initialization Vector in bytes. Length must be 8 bytes.
27
"""
28

29
import sys
1✔
30
import warnings
1✔
31

32
# PY_VER is used to handle Python2 and Python3 differences.
33
PY_VER = sys.version_info
1✔
34

35

36
def new(key, iv):
1✔
37
    """Operate this 3DES cipher."""
38

39
    return Python_TripleDES(key, iv)
1✔
40

41

42
class _baseDes(object):
1✔
43
    """The base class shared by DES and triple DES."""
44

45
    def __init__(self, iv):
1✔
46
        self.iv = iv
1✔
47

48
    def _guard_against_unicode(self, data):
1✔
49
        """Check the data for valid datatype and return them.
50

51
        Only accept byte strings or ascii unicode values.
52
        Otherwise there is no way to correctly decode the data into bytes.
53
        """
54

55
        if PY_VER < (3, ):
1!
56
            if isinstance(data, unicode):
1✔
57
                raise ValueError("Only bytes, bytearray or memoryview "
1✔
58
                                 "objects of them should be passed, "
59
                                 "not Unicode strings")
60
        else:
UNCOV
61
            if isinstance(data, str):
×
UNCOV
62
                warnings.warn("Only bytes, bytearray or memoryview "
×
63
                              "objects of them should be passed",
64
                              DeprecationWarning,
65
                              stacklevel=3)
66
                # Only accept ascii unicode values.
UNCOV
67
                try:
×
UNCOV
68
                    return data.encode('ascii')
×
UNCOV
69
                except UnicodeEncodeError:
×
UNCOV
70
                    raise ValueError("The Unicode string shouldn't be passed")
×
71
        return data
1✔
72

73
#############################################
74
#                   DES                     #
75
#############################################
76

77

78
class Des(_baseDes):
1✔
79
    """DES encryption/decryption class.
80

81
    Supports CBC (Cypher Block Chaining) mode.
82
    """
83

84
    # Permutation and translation tables for DES
85
    __pc1 = [56, 48, 40, 32, 24, 16, 8,
1✔
86
             0, 57, 49, 41, 33, 25, 17,
87
             9, 1, 58, 50, 42, 34, 26,
88
             18, 10, 2, 59, 51, 43, 35,
89
             62, 54, 46, 38, 30, 22, 14,
90
             6, 61, 53, 45, 37, 29, 21,
91
             13, 5, 60, 52, 44, 36, 28,
92
             20, 12, 4, 27, 19, 11, 3]
93

94
    # Number left rotations of pc1
95
    __left_rotations = [1, 1, 2, 2, 2, 2, 2, 2,
1✔
96
                        1, 2, 2, 2, 2, 2, 2, 1]
97

98
    # Permuted choice key (table 2)
99
    __pc2 = [13, 16, 10, 23, 0, 4,
1✔
100
             2, 27, 14, 5, 20, 9,
101
             22, 18, 11, 3, 25, 7,
102
             15, 6, 26, 19, 12, 1,
103
             40, 51, 30, 36, 46, 54,
104
             29, 39, 50, 44, 32, 47,
105
             43, 48, 38, 55, 33, 52,
106
             45, 41, 49, 35, 28, 31]
107

108
    # Initial permutation IP
109
    __ip = [57, 49, 41, 33, 25, 17, 9, 1,
1✔
110
            59, 51, 43, 35, 27, 19, 11, 3,
111
            61, 53, 45, 37, 29, 21, 13, 5,
112
            63, 55, 47, 39, 31, 23, 15, 7,
113
            56, 48, 40, 32, 24, 16, 8, 0,
114
            58, 50, 42, 34, 26, 18, 10, 2,
115
            60, 52, 44, 36, 28, 20, 12, 4,
116
            62, 54, 46, 38, 30, 22, 14, 6]
117

118
    # Expansion table for turning 32 bit blocks into 48 bits
119
    __expansion_table = [31, 0, 1, 2, 3, 4,
1✔
120
                         3, 4, 5, 6, 7, 8,
121
                         7, 8, 9, 10, 11, 12,
122
                         11, 12, 13, 14, 15, 16,
123
                         15, 16, 17, 18, 19, 20,
124
                         19, 20, 21, 22, 23, 24,
125
                         23, 24, 25, 26, 27, 28,
126
                         27, 28, 29, 30, 31, 0]
127

128
    # The (in)famous S-boxes
129
    __sbox = [  # S1
1✔
130
              [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
131
               0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
132
               4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
133
               15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
134

135
              # S2
136
              [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
137
               3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
138
               0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
139
               13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
140

141
              # S3
142
              [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
143
               13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
144
               13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
145
               1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
146

147
              # S4
148
              [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
149
               13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
150
               10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
151
               3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
152

153
              # S5
154
              [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
155
               14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
156
               4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
157
               11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
158

159
              # S6
160
              [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
161
               10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
162
               9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
163
               4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
164

165
              # S7
166
              [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
167
               13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
168
               1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
169
               6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
170

171
              # S8
172
              [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
173
               1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
174
               7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
175
               2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11], ]
176

177
    # 32-bit permutation function P used on the output of the S-boxes
178
    __p = [15, 6, 19, 20, 28, 11,
1✔
179
           27, 16, 0, 14, 22, 25,
180
           4, 17, 30, 9, 1, 7,
181
           23, 13, 31, 26, 2, 8,
182
           18, 12, 29, 5, 21, 10,
183
           3, 24]
184

185
    # Final permutation IP^-1
186
    __fp = [39, 7, 47, 15, 55, 23, 63, 31,
1✔
187
            38, 6, 46, 14, 54, 22, 62, 30,
188
            37, 5, 45, 13, 53, 21, 61, 29,
189
            36, 4, 44, 12, 52, 20, 60, 28,
190
            35, 3, 43, 11, 51, 19, 59, 27,
191
            34, 2, 42, 10, 50, 18, 58, 26,
192
            33, 1, 41, 9, 49, 17, 57, 25,
193
            32, 0, 40, 8, 48, 16, 56, 24]
194

195
    # Type of crypting being done
196
    ENCRYPT = 0x00
1✔
197
    DECRYPT = 0x01
1✔
198

199
    # Initialisation
200
    def __init__(self, key, iv=None):
1✔
201
        # Sanity checking of arguments
202
        if len(key) != 8:
1✔
203
            raise ValueError("Invalid DES key size. Key must be exactly "
1✔
204
                             "8 bytes long")
205
        super(Des, self).__init__(iv)
1✔
206

207
        self.key_size = 8
1✔
208
        self._l = []
1✔
209
        self._r = []
1✔
210
        self._kn = [[0] * 48] * 16  # 16 48-bit keys (K1 - K16)
1✔
211
        self._final = []
1✔
212

213
        self.set_key(key)
1✔
214

215
    def set_key(self, key):
1✔
216
        """Set the crypting key for this object. Must be 8 bytes."""
217

218
        self.key = key
1✔
219
        self.__create_sub_keys()
1✔
220

221
    def __string_to_bitlist(self, data):
1✔
222
        """Turn the string data into a list of bits (1, 0)'s."""
223

224
        if PY_VER < (3, ):
1!
225
            # Turn the strings into integers. Python 3 uses a bytes
226
            # class, which already has this behaviour
227
            if not isinstance(data, bytearray):
1✔
228
                data = [ord(c) for c in data]
1✔
229
        len_data = len(data) * 8
1✔
230
        result = [0] * len_data
1✔
231
        pos = 0
1✔
232
        for ch in data:
1✔
233
            i = 7
1✔
234
            while i >= 0:
1✔
235
                if ch & (1 << i) != 0:
1✔
236
                    result[pos] = 1
1✔
237
                else:
238
                    result[pos] = 0
1✔
239
                pos += 1
1✔
240
                i -= 1
1✔
241
        return result
1✔
242

243
    def __bitlist_to_string(self, data):
1✔
244
        """Turn the data as list of bits into a string."""
245

246
        result = []
1✔
247
        pos = 0
1✔
248
        c = 0
1✔
249
        while pos < len(data):
1✔
250
            c += data[pos] << (7 - (pos % 8))
1✔
251
            if (pos % 8) == 7:
1✔
252
                result.append(c)
1✔
253
                c = 0
1✔
254
            pos += 1
1✔
255

256
        if PY_VER < (3, ):
1!
257
            return ''.join([chr(c) for c in result])
1✔
258
        else:
UNCOV
259
            return bytes(result)
×
260

261
    def __permutate(self, table, block):
1✔
262
        """Permutate this block with the specified table."""
263
        return [block[x] for x in table]
1✔
264

265
    def __create_sub_keys(self):
1✔
266
        """Transform the secret key for data processing.
267

268
        Create the 16 subkeys k[1] to k[16] from the given key.
269
        """
270
        key = self.__permutate(Des.__pc1,
1✔
271
                               self.__string_to_bitlist(self.key))
272
        # Split into Left and Right sections
273
        self._l = key[:28]
1✔
274
        self._r = key[28:]
1✔
275
        for i in range(16):
1✔
276
            # Perform circular left shifts
277
            for _ in range(Des.__left_rotations[i]):
1✔
278
                self._l.append(self._l[0])
1✔
279
                del self._l[0]
1✔
280
                self._r.append(self._r[0])
1✔
281
                del self._r[0]
1✔
282

283
            # Create one of the 16 subkeys through pc2 permutation
284
            self._kn[i] = self.__permutate(Des.__pc2, self._l + self._r)
1✔
285

286
    def __des_crypt(self, block, crypt_type):
1✔
287
        """Crypt the block of data through DES bit-manipulation."""
288

289
        block = self.__permutate(Des.__ip, block)
1✔
290
        self._l = block[:32]
1✔
291
        self._r = block[32:]
1✔
292

293
        # Encryption starts from _kn[1] through to _kn[16]
294
        if crypt_type == Des.ENCRYPT:
1✔
295
            iteration = 0
1✔
296
            iteration_adjustment = 1
1✔
297
        # Decryption starts from _kn[16] down to _kn[1]
298
        else:
299
            iteration = 15
1✔
300
            iteration_adjustment = -1
1✔
301

302
        for _ in range(16):
1✔
303
            # Make a copy of _r[i-1], this will later become _l[i]
304
            temp_r = self._r[:]
1✔
305

306
            # Permutate _r[i - 1] to start creating _r[i]
307
            self._r = self.__permutate(Des.__expansion_table, self._r)
1✔
308

309
            # Exclusive or _r[i - 1] with k[i], create b[1] to b[8] whilst here
310
            self._r = [x ^ y for x, y in zip(self._r, self._kn[iteration])]
1✔
311
            b = [self._r[:6], self._r[6:12], self._r[12:18], self._r[18:24],
1✔
312
                 self._r[24:30], self._r[30:36], self._r[36:42], self._r[42:]]
313

314
            # Permutate b[1] to b[8] using the S-Boxes
315
            bn = [0] * 32
1✔
316
            pos = 0
1✔
317
            for j in range(8):
1✔
318
                # Work out the offsets
319
                m = (b[j][0] << 1) + b[j][5]
1✔
320
                n = (b[j][1] << 3) + (b[j][2] << 2) + (b[j][3] << 1) + b[j][4]
1✔
321

322
                # Find the permutation value
323
                v = Des.__sbox[j][(m << 4) + n]
1✔
324

325
                # Turn value into bits, add it to result: bn
326
                bn[pos] = (v & 8) >> 3
1✔
327
                bn[pos + 1] = (v & 4) >> 2
1✔
328
                bn[pos + 2] = (v & 2) >> 1
1✔
329
                bn[pos + 3] = v & 1
1✔
330

331
                pos += 4
1✔
332

333
            # Permutate the concatination of b[1] to b[8] (bn)
334
            self._r = self.__permutate(Des.__p, bn)
1✔
335

336
            # Xor with _l[i - 1]
337
            self._r = [x ^ y for x, y in zip(self._r, self._l)]
1✔
338
            self._l = temp_r
1✔
339

340
            iteration += iteration_adjustment
1✔
341

342
        # Final permutation of _r[16]_l[16]
343
        self._final = self.__permutate(Des.__fp, self._r + self._l)
1✔
344
        return self._final
1✔
345

346
    def crypt(self, data, crypt_type):
1✔
347
        """Crypt the data in blocks, running it through des_crypt()."""
348

349
        iv = self.__string_to_bitlist(self.iv)
1✔
350

351
        # Split the data into blocks, crypting each one seperately
352
        i = 0
1✔
353
        result = []
1✔
354
        while i < len(data):
1✔
355
            # Test code for caching encryption results
356
            block = self.__string_to_bitlist(data[i:i+8])
1✔
357

358
            # Xor with iv if using CBC mode
359
            if crypt_type == Des.ENCRYPT:
1✔
360
                block = [x ^ y for x, y in zip(block, iv)]
1✔
361

362
            processed_block = self.__des_crypt(block, crypt_type)
1✔
363

364
            if crypt_type == Des.DECRYPT:
1✔
365
                processed_block = [x ^ y for x, y in zip(processed_block, iv)]
1✔
366
                iv = block
1✔
367
            else:
368
                iv = processed_block
1✔
369

370
            # Add the resulting crypted block to our list
371
            result.append(self.__bitlist_to_string(processed_block))
1✔
372
            i += 8
1✔
373

374
        # Return the full crypted string
375
        return b''.join(result)
1✔
376

377
#############################################
378
#               Triple DES                  #
379
#############################################
380

381

382
class Python_TripleDES(_baseDes):
1✔
383
    """Triple DES encryption/decrytpion class.
384

385
    This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
386
    the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
387
    Supports CBC (Cypher Block Chaining) mode.
388
    """
389
    def __init__(self, key, iv=None):
1✔
390
        self.block_size = 8
1✔
391
        if iv:
1✔
392
            if len(iv) != self.block_size:
1✔
393
                raise ValueError("Invalid Initialization Vector (iv) must be"
1✔
394
                                 " {0} bytes long".format(self.block_size))
395
            iv = self._guard_against_unicode(iv)
1✔
396
        else:
397
            raise ValueError("Initialization Vector (iv) must be supplied")
1✔
398

399
        super(Python_TripleDES, self).__init__(iv)
1✔
400

401
        # Will set crypting key for this object. Either 16/24 bytes long.
402
        self.key_size = len(key)
1✔
403
        if self.key_size not in (16, 24):
1✔
404
            raise ValueError("Invalid triple DES key size. "
1✔
405
                             "Key must be either 16 or 24 bytes long")
406
        key = self._guard_against_unicode(key)
1✔
407

408
        self.__key1 = Des(key[:8], self.iv)
1✔
409
        self.__key2 = Des(key[8:16], self.iv)
1✔
410
        if self.key_size == 16:
1✔
411
            self.__key3 = Des(key[:8], self.iv)
1✔
412
        else:
413
            self.__key3 = Des(key[16:], self.iv)
1✔
414

415
        self.isAEAD = False
1✔
416
        self.isBlockCipher = True
1✔
417
        self.name = "3des"
1✔
418
        self.implementation = "python"
1✔
419

420
        self.__key1.iv = self.iv
1✔
421
        self.__key2.iv = self.iv
1✔
422
        self.__key3.iv = self.iv
1✔
423

424
    def encrypt(self, data):
1✔
425
        """Encrypt data and return bytes.
426

427
        data : bytes to be encrypted
428

429
        The data must be a multiple of 8 bytes and will be encrypted
430
        with the already specified key.
431
        """
432

433
        ENCRYPT = Des.ENCRYPT
1✔
434
        DECRYPT = Des.DECRYPT
1✔
435

436
        if not data:
1✔
437
            return bytearray(b'')
1✔
438

439
        data = self._guard_against_unicode(data)
1✔
440
        if len(data) % self.block_size:
1✔
441
            raise ValueError("Invalid data length, must be a multiple "
1✔
442
                             "of {0} bytes".format(self.block_size))
443

444
        i = 0
1✔
445
        result = []
1✔
446
        while i < len(data):
1✔
447
            block = self.__key1.crypt(data[i:i+8], ENCRYPT)
1✔
448
            block = self.__key2.crypt(block, DECRYPT)
1✔
449
            block = self.__key3.crypt(block, ENCRYPT)
1✔
450
            self.__key1.iv = block
1✔
451
            self.__key2.iv = block
1✔
452
            self.__key3.iv = block
1✔
453
            result.append(block)
1✔
454
            i += 8
1✔
455

456
        return bytearray(b''.join(result))
1✔
457

458
    def decrypt(self, data):
1✔
459
        """Decrypt data and return bytes.
460

461
        data : bytes to be encrypted
462

463
        The data must be a multiple of 8 bytes and will be decrypted
464
        with the already specified key.
465
        """
466
        ENCRYPT = Des.ENCRYPT
1✔
467
        DECRYPT = Des.DECRYPT
1✔
468

469
        if not data:
1✔
470
            return bytearray(b'')
1✔
471

472
        data = self._guard_against_unicode(data)
1✔
473
        if len(data) % self.block_size:
1✔
474
            raise ValueError("Invalid data length, must be a multiple "
1✔
475
                             "of {0} bytes".format(self.block_size))
476

477
        i = 0
1✔
478
        result = []
1✔
479
        while i < len(data):
1✔
480
            iv = data[i:i+8]
1✔
481
            block = self.__key3.crypt(iv, DECRYPT)
1✔
482
            block = self.__key2.crypt(block, ENCRYPT)
1✔
483
            block = self.__key1.crypt(block, DECRYPT)
1✔
484
            self.__key1.iv = iv
1✔
485
            self.__key2.iv = iv
1✔
486
            self.__key3.iv = iv
1✔
487
            result.append(block)
1✔
488
            i += 8
1✔
489
        data = b''.join(result)
1✔
490

491
        return bytearray(data)
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

© 2025 Coveralls, Inc