From 8b97baab15577c30f550d4fea660faab83307590 Mon Sep 17 00:00:00 2001 From: siohaza Date: Tue, 8 Jul 2025 15:14:11 +0300 Subject: [PATCH 1/2] build(requirements): add pprp --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f1aac1d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pprp==0.2.6 From 60ef5e0d33555480a975f13c6d77e2c1ada8bc2d Mon Sep 17 00:00:00 2001 From: siohaza Date: Tue, 8 Jul 2025 15:28:09 +0300 Subject: [PATCH 2/2] feat: add EAC log checksums generation --- eaclogger/logger/eac.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/eaclogger/logger/eac.py b/eaclogger/logger/eac.py index 9a48d2b..2d0f1f6 100755 --- a/eaclogger/logger/eac.py +++ b/eaclogger/logger/eac.py @@ -1,6 +1,6 @@ import eaclogger import time -import hashlib +import pprp import whipper from whipper.common import common from whipper.result import result @@ -205,13 +205,36 @@ def logRip(self, ripResult, epoch): lines.append("End of status report") lines.append("") - # Log checksum (uppercase hex encoded SHA256 hash of all lines) - # It isn't compatible with EAC's one: checklog fail - lines.append("") - hasher = hashlib.sha256() - hasher.update("\n".join(lines).encode("utf-8")) - lines.append("==== Log checksum %s ====" % hasher.hexdigest().upper()) + # Log checksum + # Based off https://github.com/puddly/eac_logsigner + text = ''.join(lines) + + # Setup Rijndael-256 with a 256-bit blocksize + cipher = pprp.crypto_3.rijndael( + key = bytes(bytearray.fromhex('9378716cf13e4265ae55338e940b376184da389e50647726b35f6f341ee3efd9')), + block_size = 256 // 8 + ) + + # Encode the text as UTF-16-LE + plaintext = text.encode('utf-16-le') + + # The IV is all zeroes so we don't have to handle it + signature = b'\x00' * 32 + + # Process it block-by-block + for i in range(0, len(plaintext), 32): + # Zero-pad the last block, if necessary + plaintext_block = plaintext[i:i + 32].ljust(32, b'\x00') + + # CBC mode (XOR the previous ciphertext block into the plaintext) + cbc_plaintext = bytes(a ^ b for a, b in zip(signature, plaintext_block)) + + # New signature is the ciphertext. + signature = cipher.encrypt(cbc_plaintext) + + # Textual signature is just the hex representation lines.append("") + lines.append(f"==== Log checksum {signature.hex().upper()} ====") return lines