TapHome

Šifrování a haše

Funkce skriptu TapHome pro šifrované a podepsané protokoly zařízení: AESENCRYPT a AESDECRYPT, HASH a HMAC s MD5 a SHA, RANDBYTES a příklad brány Bosch KM200.

Šifrovací a hašovací funkce sestaví to, co očekává zařízení se šifrovaným nebo podepsaným místním rozhraním: šifrování AES, haše MD5 a SHA, podpisy HMAC a bezpečné náhodné bajty. Pouze sestavují hodnoty, takže fungují v každém skriptu. Všechny potřebují Core 2026.1 v TapHome Next, build 40991 nebo novější (zatím ne v oficiálním vydání). Base64, šestnáctkový text a kontrolní součty CRC jsou na stránce Kódování bajtů a kontrolní součty.

Přijímají bajtová data: collection<uint8>, blob nebo řetězec. Řetězec se použije jako bajty ISO-8859-1. Na rozdíl od TOBYTES bez kódování, která jiné znaky změní na ?, je zde znak mimo ISO-8859-1 chybou — pro UTF-8 předejte TOBYTES(text, "utf-8"). Výsledek je collection<uint8>.

HASH, HMAC

HASH spočítá haš bajtových dat, HMAC jejich haš s klíčem (podpis).

1
2
HASH(data, algorithm)
HMAC(key, data, algorithm)
NázevPopis
dataBajtová data k hašování.
keyKlíč funkce HMAC, bajtová data.
algorithm"MD5", "SHA1", "SHA256" nebo "SHA512", na velikosti písmen nezáleží; přijímají se i "SHA-1", "SHA-256" a "SHA-512".

Vrací — collection<uint8> o 16, 20, 32 nebo 64 bajtech.

Poznámky — HMAC bere klíč jako první, ve stejném pořadí jako hmac.new(key, msg, digest) v Pythonu.

Příklad

TOHEX(HASH("abc", "MD5"));
# Result: "900150983cd24fb0d6963f7d28e17f72"
TOHEX(HMAC("Jefe", "what do ya want for nothing?", "SHA256"));
# Result: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"

Chyby — HASH Unknown algorithm. Valid values are ‘MD5’, ‘SHA1’, ‘SHA256’, ‘SHA512’; HASH - data contains characters outside ISO-8859-1, convert the text with TOBYTES(text, “utf-8”); HASH - data must be a uint8 collection, a blob or a string. Hlášení funkce HMAC začínají jejím vlastním názvem a jmenují argument.

Dostupnost — Core 2026.1 v TapHome Next, build 40991 nebo novější (zatím ne v oficiálním vydání).

AESENCRYPT, AESDECRYPT

AESENCRYPT zašifruje bajtová data algoritmem AES, AESDECRYPT je dešifruje.

1
2
AESENCRYPT(data, key, mode [, iv])
AESDECRYPT(data, key, mode [, iv])
NázevPopis
dataBajtová data. Data pro AESDECRYPT musí mít délku, která je násobkem 16 bajtů.
key16, 24 nebo 32 bajtů: AES-128, AES-192 nebo AES-256.
mode"ECB" nebo "CBC", za kterým může následovat doplnění, například "CBC/PKCS7" nebo "ECB/ZEROS"; na velikosti písmen nezáleží.
iv16 bajtů, povinný u CBC. ECB ho nebere — argument vynechte nebo předejte Null.
Doplnění (padding)AESENCRYPTAESDECRYPT
/PKCS7 (výchozí; /PKCS5, název z Javy, znamená totéž)Přidá doplnění.Odstraní ho.
/ZEROSDoplní poslední blok bajty 0x00; data, která už končí na hranici bloku, nedostanou nic, prázdná data zůstanou prázdná.Odstraní všechny koncové bajty 0x00, i ty, které patří k datům — použijte ho pro text, například JSON.
/NONEBez doplnění; délka dat musí být násobkem 16 bajtů.Neodstraní nic.

Vrací — collection<uint8>.

Poznámky — Špatný klíč dokáže odhalit jen /PKCS7, a ani to vždy; u /ZEROS a /NONE vrátí špatný klíč špatné bajty bez chyby. Špatný iv v režimu CBC poškodí jen prvních 16 bajtů a nikdy se nenahlásí.

Příklad

VAR key := BYTECOLLECTION("2b7e151628aed2a6abf7158809cf4f3c");
VAR iv := BYTECOLLECTION("000102030405060708090a0b0c0d0e0f");
VAR secret := AESENCRYPT("Hello World", key, "CBC", iv);
TOSTRING(AESDECRYPT(secret, key, "CBC", iv));
# Result: "Hello World"

Chyby — AESDECRYPT - decryption failed, check the key, the iv and the padding (doplnění /PKCS7 nesedí: špatný klíč nebo data, která nebyla zašifrována s PKCS7); AESENCRYPT - key must be 16, 24 or 32 bytes long (AES-128, AES-192, AES-256), it is N; AESENCRYPT - CBC mode needs a 16-byte iv, it is N; AESENCRYPT - ECB mode does not use an iv, leave the argument out; AESENCRYPT Unknown mode. Valid values are ‘ECB’, ‘CBC’, optionally followed by ‘/PKCS7’ (or ‘/PKCS5’), ‘/ZEROS’ or ‘/NONE’; AESENCRYPT - with padding NONE the data length must be a multiple of 16 bytes, it is N; AESDECRYPT - encrypted data length must be a multiple of 16 bytes, it is N. Každá funkce uvádí v hlášení svůj název.

Dostupnost — Core 2026.1 v TapHome Next, build 40991 nebo novější (zatím ne v oficiálním vydání).

RANDBYTES

RANDBYTES vrátí kryptograficky bezpečné náhodné bajty — pro iv režimu CBC, nonce nebo klíč relace.

1
RANDBYTES(count)

Vrací — collection<uint8> s count bajty, 1 až 2048; totéž jako secrets.token_bytes(n) nebo os.urandom(n) v Pythonu.

Poznámky

  • RAND a RANDINT nejsou bezpečné a na klíč, iv ani nonce se nesmí použít.
  • Proměnná s kolekcí přiřazená do jiné proměnné je táž kolekce, proto před APPEND udělejte COPY — jinak naroste i iv.

Příklad — nový iv před zašifrovanými daty, jak ho posílá mnoho protokolů

VAR key := FROMHEX("2b7e151628aed2a6abf7158809cf4f3c");
VAR iv := RANDBYTES(16);
VAR body := COPY(iv);
APPEND(body, AESENCRYPT("Hello World", key, "CBC", iv));
TOSTRING(AESDECRYPT(COPY(body, 16), key, "CBC", COPY(body, 0, 16)));
# Result: "Hello World"

Chyby — RANDBYTES: count must be between 1 and 2048.

Dostupnost — Core 2026.1 v TapHome Next, build 40991 nebo novější (zatím ne v oficiálním vydání).

Příklad — brána Bosch / Buderus KM200

HTTP rozhraní brány Bosch / Buderus KM200, kterou používá i IVT Rego 2000, tak, jak ho popisují komunitní projekty (výrobce ho nezveřejňuje). Tělo odpovědi je Base64 z dat AES-256-ECB doplněných nulami a klíč se skládá ze dvou hašů MD5:

VAR salt := BYTECOLLECTION("00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff");  # 32-byte vendor salt
VAR k1 := TOBYTES(REPLACE("xxxx-xxxx-xxxx-xxxx", "-", ""));    # gateway password
APPEND(k1, salt);
VAR k2 := COPY(salt);
APPEND(k2, TOBYTES("my private password"));
VAR key := HASH(k1, "MD5");
APPEND(key, HASH(k2, "MD5"));                                  # 32 bytes = AES-256

VAR r := SENDHTTPREQUEST("/system/healthStatus", "GET", "", "User-Agent: TeleHeater/2.2.3");
# value = a module variable that keeps the result
IF r.IsSuccess
    value := PARSEJSON(TOSTRING(AESDECRYPT(FROMBASE64(r.Content), key, "ECB/ZEROS"), "utf-8"), "value");
ELSE
    ADDERROR(r.StatusCode + " (" + r.ReasonPhrase + ")");
END

Viz také — Funkce Packet parser, Kódování bajtů a kontrolní součty, Text a kolekce.