Client-side SCP80 decryption: pure-JS 3DES/AES with user-supplied keys
Adds optional decryption of ciphered secured packets, entirely in the browser — the key never leaves the frontend. - decode.py: _decode_secured_packet exposes 'cipher_block' (the contiguous on-wire ciphered octets CNTR..end, ready for CBC) and raw kic/kid bytes for algorithm selection. Additive only. - index.html: pure-JS DES/3DES core (FIPS 46-3 bit-array tables, parity ignored) + CBC; AES-CBC via native SubtleCrypto; both with zero IV per TS 102 225. decryptSecured() picks the algorithm from the KIc nibble (02 AES-CBC, 05 3DES-2K, 09 3DES-3K, 01 DES) with key-length validation. - UI: ciphered packets show a key-hex input + Decrypt strip below the detail table; keys are memoized per key-set for the session in an in-memory OTA_KEYS map — never sent to the server, never persisted. - Decrypted results cached by cipher_block (survive live-polling re-renders); plaintext rows rendered as CNTR/PCNTR/RC/Secured data (decrypted) alongside the ciphertext; wrong-key guard via the decrypted padding counter (PCNTR > remaining → "invalid padding"). - 3DES implementation validated byte-identical against openssl des-ede3-cbc (3-key, 2-key ×3 random vectors, single-key). No CC verification (out of scope). Tests: +2 (cipher_block contiguity, AES registry guard) — 350 total. Version 1.19.0, SW cache simtrace-analyser-v27.
This commit is contained in:
1 parent
840e233baf
commit
d21997764f
7 files changed
+253
-5
No files matched your search
@@ -6,7 +6,7 @@ from .gsmtap import GsmtapSender, GsmtapReceiver
|
||||
from .pcap import PcapWriter
|
||||
from .dump import FileDumper, format_message
|
||||
|
||||
__version__ = '1.18.0'
|
||||
__version__ = '1.19.0'
|
||||
__all__ = [
|
||||
'SniffSession',
|
||||
'DeviceDisconnected',
|
||||
|
||||
@@ -2335,6 +2335,12 @@ def _decode_secured_packet(body):
|
||||
'cntr': cntr.hex().upper(),
|
||||
'pcntr': pcntr,
|
||||
'data': data.hex().upper(),
|
||||
# Contiguous ciphered on-wire octets (CNTR ‖ PCNTR ‖ RC/CC/DS ‖
|
||||
# secured data + padding) — the block a client-side decryptor
|
||||
# feeds to 3DES/AES-CBC with a zero IV (TS 102 225 Table 2 n.1).
|
||||
'cipher_block': body[10:].hex().upper(),
|
||||
'kic_raw': kic,
|
||||
'kid_raw': kid,
|
||||
}
|
||||
kic_algo = _KIC_ALGO.get(kic & 0x0F, 'reserved')
|
||||
if not (spi1 & 0x04): # SPI says no ciphering → KIc unused
|
||||
|
||||
Reference in new issue
Block a user