Criptare și hash-uri
Funcții de script TapHome pentru protocoale de dispozitive criptate și semnate: AESENCRYPT și AESDECRYPT, HASH și HMAC cu MD5 și SHA, RANDBYTES și un exemplu pentru Bosch KM200.
Funcțiile de criptare și hash construiesc ceea ce așteaptă un dispozitiv cu o interfață locală criptată sau semnată: criptare AES, hash-uri MD5 și SHA, semnături HMAC și octeți aleatori siguri. Ele doar construiesc valori, așa că funcționează în orice script. Toate necesită Core 2026.1 pe TapHome Next, build 40991 sau mai nou (încă nu este în versiunea oficială). Base64, textul hexazecimal și sumele de control CRC se află în Codificări de octeți și sume de control.
Primesc date de octeți: o collection<uint8>, un blob sau un șir. Un șir se folosește ca octeți ISO-8859-1. Spre deosebire de TOBYTES fără codificare, care transformă celelalte caractere în ?, un caracter din afara ISO-8859-1 este aici o eroare — pentru UTF-8 transmiteți TOBYTES(text, "utf-8"). Rezultatul este o collection<uint8>.
HASH, HMAC
HASH calculează hash-ul datelor de octeți, HMAC un hash cu cheie (o semnătură) al acestora.
| |
| Nume | Descriere |
|---|---|
data | Datele de octeți pentru care se calculează hash-ul. |
key | Cheia funcției HMAC, date de octeți. |
algorithm | "MD5", "SHA1", "SHA256" sau "SHA512", fără deosebire între majuscule și minuscule; se acceptă și "SHA-1", "SHA-256" și "SHA-512". |
Returnează — collection<uint8> de 16, 20, 32 sau 64 de octeți.
Observații — HMAC primește întâi cheia, în aceeași ordine ca hmac.new(key, msg, digest) din Python.
Exemplu
TOHEX(HASH("abc", "MD5"));
# Result: "900150983cd24fb0d6963f7d28e17f72"
TOHEX(HMAC("Jefe", "what do ya want for nothing?", "SHA256"));
# Result: "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"Erori — 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. Mesajele funcției HMAC încep cu propriul ei nume și numesc argumentul.
Disponibilitate — Core 2026.1 pe TapHome Next, build 40991 sau mai nou (încă nu este în versiunea oficială).
AESENCRYPT, AESDECRYPT
AESENCRYPT criptează date de octeți cu AES, AESDECRYPT le decriptează.
| |
| Nume | Descriere |
|---|---|
data | Date de octeți. Datele pentru AESDECRYPT trebuie să aibă o lungime multiplu de 16 octeți. |
key | 16, 24 sau 32 de octeți: AES-128, AES-192 sau AES-256. |
mode | "ECB" sau "CBC", urmat opțional de completare, de exemplu "CBC/PKCS7" sau "ECB/ZEROS"; fără deosebire între majuscule și minuscule. |
iv | 16 octeți, cerut de CBC. ECB nu îl folosește — omiteți argumentul sau transmiteți Null. |
| Completare (padding) | AESENCRYPT | AESDECRYPT |
|---|---|---|
/PKCS7 (implicit; /PKCS5, numele din Java, înseamnă același lucru) | Adaugă completarea. | O elimină. |
/ZEROS | Umple ultimul bloc cu octeți 0x00; datele care se termină deja la granița unui bloc nu primesc nimic, datele goale rămân goale. | Elimină toți octeții 0x00 de la final, și pe cei care aparțin datelor — folosiți-o pentru text precum JSON. |
/NONE | Fără completare; lungimea datelor trebuie să fie multiplu de 16 octeți. | Nu elimină nimic. |
Returnează — collection<uint8>.
Observații — Doar /PKCS7 poate observa o cheie greșită, și nici aceasta întotdeauna; cu /ZEROS și /NONE o cheie greșită returnează octeți greșiți fără eroare. Un iv greșit în CBC strică doar primii 16 octeți și nu este raportat niciodată.
Exemplu
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"Erori — AESDECRYPT - decryption failed, check the key, the iv and the padding (completarea /PKCS7 nu se potrivește: o cheie greșită sau date care nu au fost criptate cu 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. Fiecare funcție își scrie propriul nume în mesaj.
Disponibilitate — Core 2026.1 pe TapHome Next, build 40991 sau mai nou (încă nu este în versiunea oficială).
RANDBYTES
RANDBYTES returnează octeți aleatori siguri din punct de vedere criptografic — pentru un iv al modului CBC, un nonce sau o cheie de sesiune.
| |
Returnează — collection<uint8> de count octeți, între 1 și 2048; același lucru ca secrets.token_bytes(n) sau os.urandom(n) din Python.
Observații
- RAND și RANDINT nu sunt sigure și nu trebuie folosite pentru o cheie, un
ivsau un nonce. - O variabilă colecție atribuită altei variabile este aceeași colecție, așa că faceți o
COPYînainte de a adăuga cuAPPEND— altfel crește șiiv.
Exemplu — un iv nou în fața datelor criptate, așa cum îl trimit multe protocoale
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"Erori — RANDBYTES: count must be between 1 and 2048.
Disponibilitate — Core 2026.1 pe TapHome Next, build 40991 sau mai nou (încă nu este în versiunea oficială).
Exemplu — gateway Bosch / Buderus KM200
Interfața HTTP a unui gateway Bosch / Buderus KM200, folosit și de IVT Rego 2000, așa cum o descriu proiectele comunității (producătorul nu o publică). Corpul răspunsului este Base64 din date AES-256-ECB completate cu zerouri, iar cheia este formată din două hash-uri 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 + ")");
ENDConsultați și — Funcții Packet parser, Codificări de octeți și sume de control, Text și colecții.