/
serpent.py
73 lines (60 loc) · 2.18 KB
/
serpent.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
from typing import List, Optional
from refinery.units.crypto.cipher import (
Arg,
StandardBlockCipherUnit,
)
from refinery.lib.serpent import (
make_subkeys,
serpent_encrypt,
serpent_decrypt,
)
from refinery.lib.crypto import (
BlockCipher,
BlockCipherFactory,
BufferType,
CipherMode,
CipherInterface,
)
class Serpent(BlockCipher):
_key_data: List[int]
_key_derivation: List[int]
block_size = 0x10
key_size = frozenset(range(4, 0x101, 4))
def __init__(self, key: BufferType, mode: Optional[CipherMode], swap: bool = True):
super().__init__(key, mode)
self.swap = swap
def block_decrypt(self, block) -> BufferType:
return serpent_decrypt(block, self.key, self.swap)
def block_encrypt(self, block) -> BufferType:
return serpent_encrypt(block, self.key, self.swap)
@property
def key(self):
try:
return self._key_derivation
except AttributeError:
kd = make_subkeys(self._key_data)
self._key_derivation = kd
return kd
@key.setter
def key(self, key):
self._key_data = key
class serpent(StandardBlockCipherUnit, cipher=BlockCipherFactory(Serpent)):
"""
Serpent encryption and decryption. Some Serpent implementations read the bytes of each block
in one direction, some in the other. When decryption results with this unit do not yield the
expected result, try using the `--swap` (or `-s`) option to swap the bytes in each block.
Furthermore, it is sometimes necessary to swap the bytes of the input key, which can be done
by prefixing the input key by the multibin handler `snip[::-1]`.
"""
def __init__(
self, key, iv=b'', padding=None, mode=None, raw=False,
swap: Arg.Switch('-s', help='Read the bytes in each block in reverse order.') = False
):
super().__init__(key, iv, padding=padding, mode=mode, raw=raw, swap=swap)
def _new_cipher(self, **optionals) -> CipherInterface:
instance: Serpent = super()._new_cipher()
instance.swap = self.args.swap
return instance