FULL-C secure httpget example

Z onlinetechnology.cz

Přejít na: navigace, hledání
Tato stránka popisuje programovací jazyk FULL-C, který je dostupný na vybraných zařízeních SDS. Některá zařízení používají SDS-C, pro který máme návody jinde na této WiKi.

Pozor

V aktuálním vzorovém programu je chyba, a to u některých volání funkce snprintf(), kde "n" je o jednotku menší než by mělo být. Oprava se chystá a bude vydána, do té doby si to opravte ručně sami.

Funkce snprintf() totiž do "n" započítává i trailing zero (0x00) na konci stringu, a na to se občas zapomělo.


Obsah


Přenos dat

Hlavním důvodem pro existenci SDS je, kromě vlastní (místní) "inteligence" ve formě FULL-C programu, právě přenos dat ze zařízení SDS na server.

Tento přenos umožňuje průběžné záznamy činnosti (např. průběžné měření energie), a současně i volitelnou zpětnou vazbu (např. ovládání SDS ze serveru).

Toto vše je v dnešní době potřeba provést zabezpečeně: server musí autentifikovat (ověřit totožnost) zařízení SDS, a přenášené informace musí být zabezpečeny (šifrovány) tak, aby je nikdo nezvaný nemohl přečíst a nebo pozměnit (tamper).

Šifrování je založeno na sdíleném tajemství, kterým je (128-bitový) symetrický klíč. Další detaily jsou postupně uvedeny na této stránce.

Toto vše řeší následující úplný příklad, který se zkládá ze vzorového FULL-C programu pro SDS a vzorového PHP programu pro server. Protože jsou k dispozici všechny zdrojové kódy, není problém si tento příklad upravit přesně dle svých potřeb.


Podmínka

Základem je použití firmware v zařízení SDS od 30.11.2015 (toto nebo novější).


Princip

Základem je sestavení datové zprávy (plain-text) v SDS, která má být odeslána do serveru. Zpráva je vedena jako jeden souvistlý textový řetezec - proto je potřeba použít vhodný oddělovač mezi jednotlivými položkami (oblíbený je znak "svislítko" '|'), aby se např. v PHP dala s výhodou použít funkce explode().

Tato zpráva je na SDS zašifrována (XTEA-CTR, unikátním klíčem dle admin-nastavení v SDS, a pokaždé jiným IV), zabalena do Base64-SafeURL, a následně odeslána pomocí HTTP-GET na server.

Díky tomu, že je zpráva šifrována, můžeme si bez obav dovolit použít "obyčejný" HTTP-GET. Toto řešení nabízí unikátní spolehlivost (bezproblémový průchod přes firewally a proxy) je dlouhodobě ověřené. Výhodou HTTP-GET je to, že všechny informace jsou přímo v GET dotazu (v URI), takže se nemá co ztratit. To že si URI někdo přečte je bez významu, protože díky specifickému šifrování (unikátní IV pro každý průchod) jsou data při každém GET jiná.

Server HTTP-GET přijme, provede ověření platnosti Base64 a dékodování, následně ověří hlavičku protokolu a pak provede dešifrování. Vzniklý plain-text je následnĚ prověřen na platnost (je ověřeno klíčové slovo, které dokazuje že původní informace byla šifrovaná na SDS s daným symetrickým klíčem). Teprve až vše "projde", je poskytnut výsledek (původni text sestavený v SDS) pro další zpracování (např. uložení hodnot do databáze).


Bezpečnost

Šifrování: XTEA-CTR Klíč: symetrický klíč, 128-bit, zadávaný jako 32 Hex-Nibble znaky (do SDS Web Admin a také na serveru) IV: 64-bit, vytvářen jako náhodné číslo na SDS pro každé odesílání na server, přenášen v protokolu

Zabezpečení:

  • proti odposlechu (přenáší se šifrovaná data)
  • proti změně (tamper) - jakákoliv změna šifrovaných dat se detekuje
  • autentizace - přijatá je pouze zpráva šifrovaná správným klíčem (jiný klíč způsobí označení zprávy za neplatnou)

Přenos na server: jediný GET dotaz, data v URI zakódována pomocí Base64-SafeURL mechanismu.


Realizace

Blokové schéma je na následujícím obrázku. Jsou použity dva základní bloky - a to FULL-C program, a část na serveru (v tomto příkladu v PHP, ale může být samozřejmě v jakémkoliv programovacím jazyce).

sds_fullc_enc_httpget_oneway.png


Základem je společný "CRYPTO KEY". Ten je potřeba zadat v SDS (webová administrace) a samozřejmě na serveru. Pouze ty části, které mají stejný klíč, budou spolu schopny komunikovat.

Šifrování je založeno na algoritmu XTEA-CTR, využívá se FULL-C funkce SDS_crypto().

Vše lze jednoznačně vidět ze zdrojových kódů tohoto příkladu.


  • První krok: sestavení datového řetězce (plain-text), který má být přenesen na server

V aktuální verzi firmware SDS je následující omezení (z důvodů maximální přenesené velikosti dat přes http_get() funkci):

 //  SDS: has a limit on maximal HTTP GET string size = (1500-48) = 1452 bytes
 //  This is the size of the final Base64 encoding output !
 //
 //  The maximal Base64 INPUT should be = (((4 * 1086) / 3) + 3) & (~3) = 1450
 //  because 1450 is lower than 1452 (but the closest we can make).
 //
 #define ENCPROTOCOLhdrSIZE              (23)   // bytes
 //
 //  The input contains the 23 bytes of header and the X bytes of encrypted plain-text.
 //  Therefore the maximal length of plain-text is 1063,
 //  and its closest mul16 number is 1056 bytes ! (1056 / 16 = 66 and no remainder !)
 //
 #define HTTPGET_PLAINTEXT_FOR_B64_LIMIT (1056) // (which is 1063 rounded to closest multiply of 16)
 // 

Jak lze vidět, je zde omezení na 1452 znaků, které umí http_get() přenést. Protože do těchto 1452 znaků dáváme výsledek Base64-URL převodu, bude originál muset být menší (protože Base64-URL data "nafukuje"). Současně, nesmíme zapomenou na hlavičku, která se přidává k šifrovaným informacím (a oboje pak slouží jako vstup do Base64-URL), tato hlavička má v současné verzi protokolu přesně 23 bajtů. Toto vše je potřeba zaokrouhlit na násobek 16.

Výsledek tedy je, že největší plain-text, který lze na server přenést, může být maximálně 1056 bajtů (znaků) dlouhý.

 char *PlaintextBuf;
 
 // allocate the memory - always allocate the full maximal buffer
 PlaintextBuf = (char *)malloc(HTTPGET_PLAINTEXT_FOR_B64_LIMIT);
 
 // print the contents (this is exactly the text we want to send to cloud!)
 // (in fact, with a minimal modification, we can send any binary data)
 snprintf(PlaintextBuf,
          HTTPGET_PLAINTEXT_FOR_B64_LIMIT,
          /* %cSDS = required by protocol, do not touch ! */
          /* you can freely edit any further items, following the %cSDS : */
          "%cSDS|u1=%u|i2=%d|s3=%s|f4=%f|",
          /* %c= */ 'a'+randCounter,
          /* u1= */ 10,
          /* i2= */ -20,
          /* s3= */ "abcdef",
          /* f4= */ 25.54
         );

Tento kód provede zápis do PlaintextBuf. Jak lze vidět, používáme snprintf() což je délkově-omezený, formátovaný zápis do PlaintextBuf bufferu, který jsme o řádek výše alokovali na paměťové haldě (heap) - po ukončení odesílání paměť zase uvolníme.

Všimněte si, že kromě zápisu vlastního textu, o který nám jde (v tomto příkladu: "u1=%u|i2=%d|s3=%s|f4=%f|") jsme přidali úplně na začátek tuto sekvenci znaků : "%cSDS".

Sekvence "%cSDS" má dva významy: (1) zaručuje že pokaždé bude šifrovaný výsledek vypadat jinak, a (2) že ověříme platnost odesílatele, protože pouze ten, kdo provede šifrování jediným správným klíčem, dokáže na straně příjemce vytvořit správný text, ve kterém bude právě to "SDS". Toto je klíčová vlastnost (autentizace) protokolu.

Zbytek printu je už zřejmý, tam si dejte co potřebujete přenést na server, a toto vám následující kód na serveru i vrátí (a pozor, už bez "%cSDS" !).


  • Druhý krok: zabalení a odeslání

Vše se provede v pod-funkci, viz následující kus kódu:

 // proceed - encapsulate, encrypt, base64url, and finally -> send
 HTTP_GET_SECURE_SEND_STRING_TO_WEB(PlaintextBuf);
 
 // FINALLY - never forget to release the allocated memory !
 
 // finish - free
 free(PlaintextBuf); PlaintextBuf = 0;

Samozřejmě po návratu z této funkce nesmíte zapomenout uvolnit předtím alokovanou pamět (viz malloc() nahoře).

Zdrojový kód (obsah) této funkce je k dispoizici v přiloženém kompletním zdrojovém kódu.


Strana serveru

Příklad zde uvedený ukazuje řešení v PHP programovacím jazyce. Samozřejmě že tuto záležitost lze realizovat i v jiných jazycích.


Všechny potřebné soubory ke stažení

Kompletní příklad je k dispizici (v ZIP archivu) ke stažení a použití.

Obsah:

  • enc_http_send.c = program ve FULL-C, který se nahrává do zařízení SDS. Nezapomeňte jej upravit tak, aby odkazoval na váš server. Zkontrolujte si všechny snprintf() jestli mají správně nastavené limity.
  • test.php = tento skript nahrajete na váš server, a nezapomeňte jej upravit dle svých potřeb (plus zadat správný, stejný, klíč jako je v SDS).
  • SDScode.php = toto je skript který se stará o dešifrovaní a validaci přijatých dat; zde nemusíte nic měnit. Tento skript obsahuje funkce odkazované z test.php.


DOWNLOAD SDS EXAMPLE HERE

Dotazy

Pište na naše fórum.

Osobní nástroje
Translate