forked from fsantini/python-e3dc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_RSCPEncryptDecrypt.py
More file actions
96 lines (77 loc) · 3.06 KB
/
_RSCPEncryptDecrypt.py
File metadata and controls
96 lines (77 loc) · 3.06 KB
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import math
from py3rijndael import RijndaelCbc, ZeroPadding # type: ignore
KEY_SIZE = 32
BLOCK_SIZE = 32
class ParameterError(Exception):
"""Class for Parameter Error Exception."""
pass
def zeroPad_multiple(string: bytes, value: int) -> bytes:
"""Zero padding string."""
length = len(string)
if length % value == 0:
return string
newL = int(value * math.ceil(float(length) / value))
return string.ljust(newL, b"\x00")
def truncate_multiple(string: bytes, value: int) -> bytes:
"""Truncating sting."""
length = len(string)
if length % value == 0:
return string
newL = int(value * math.floor(float(length) / value))
return string[:newL]
class RSCPEncryptDecrypt:
"""A class for encrypting and decrypting RSCP data."""
def __init__(self, key: bytes):
"""Constructor of a RSCP encryption and decryption class.
Args:
key (bytes): RSCP encryption key
"""
if len(key) > KEY_SIZE:
raise ParameterError("Key must be <%d bytes" % (KEY_SIZE))
self.key = key.ljust(KEY_SIZE, b"\xff")
self.encryptIV = b"\xff" * BLOCK_SIZE
self.decryptIV = b"\xff" * BLOCK_SIZE
self.remainingData = b""
self.oldDecrypt = b""
def encrypt(self, plainText: bytes) -> bytes:
"""Method to encryt plain text."""
encryptor = RijndaelCbc(
self.key,
self.encryptIV,
padding=ZeroPadding(BLOCK_SIZE),
block_size=BLOCK_SIZE,
)
encText = encryptor.encrypt(plainText)
self.encryptIV = encText[-BLOCK_SIZE:]
return encText
def decrypt(
self, encText: bytes, previouslyProcessedData: int | None = None
) -> bytes:
"""Method to decryt encrypted text."""
if previouslyProcessedData is None:
length = len(self.oldDecrypt)
if length % BLOCK_SIZE == 0:
previouslyProcessedData = length
else:
previouslyProcessedData = int(
BLOCK_SIZE * math.floor(length / BLOCK_SIZE)
)
# previouslyProcessedData was passed by the parent: it means that a frame was decoded and there was some data left. This does not include the padding zeros
if previouslyProcessedData % BLOCK_SIZE != 0:
previouslyProcessedData = int(
BLOCK_SIZE * math.ceil(previouslyProcessedData / BLOCK_SIZE)
)
remainingData = self.oldDecrypt[previouslyProcessedData:]
if self.oldDecrypt != b"":
self.decryptIV = self.oldDecrypt[
previouslyProcessedData - BLOCK_SIZE : previouslyProcessedData
]
self.oldDecrypt = encText # save current block
toDecrypt = truncate_multiple(remainingData + encText, BLOCK_SIZE)
decryptor = RijndaelCbc(
self.key,
self.decryptIV,
padding=ZeroPadding(BLOCK_SIZE),
block_size=BLOCK_SIZE,
)
return decryptor.decrypt(toDecrypt) # pyright: ignore [reportUnknownMemberType]