ArduinoJWT knihovna

Odpovědět
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

ArduinoJWT knihovna

Příspěvek od hubacekp »

Ahoj,
pro enkryptování JSON Stringů a posílání přes nezabezpečené HTTP (Arduino jiné neumí) jsem našel knihovnu ArduinoJWT, která ale neobsahovala žádný příklad a autor na to asi už nemá čas.
Vypadala funkční, něco jsem v tom upravil, přidal jsem jeden příklad, enkryptuje mi to, teď řeším už jen jeden problém
https://gitlab.com/petrhu/ArduinoJWT

Problém: při decryptu zpět na JSON se rozšifrovaný řetězec nachází v souboru ArduinoJWT.cpp, v proměnné typu pole jsonPayload.
celý příklad ArduinoJWT_JSON_jwt.ino: https://gitlab.com/petrhu/ArduinoJWT/bl ... ON_jwt.ino
Soubor ArduinoJWT.cpp s problematickou částí: https://gitlab.com/petrhu/ArduinoJWT/bl ... inoJWT.cpp

Dokážu z toho JSON vypsat na serial:

Kód: Vybrat vše

      for(int i=0 ; i < payloadLength ; i++){
        Serial.print(char(jsonPayload[i]));
      }
ale nedaří se mi uložit proměnnou a vrátit ji funkcí - je prázdná:
payload = String(jsonPayload);

zde je dotčená funkce ze souboru ArduinoJWT.cpp. Dokázali byste mi poradit kde dělám nějakou začátečnickou chybu?

Kód: Vybrat vše

/* Library problematic part to be solved in ArduinoJWT.cpp*/

bool ArduinoJWT::decodeJWT(String& jwt, String& payload) {

  int payloadLength = getJWTPayloadLength(jwt);
  
  if(payloadLength > 0) {
  
    char jsonPayload[payloadLength];
    
    if(decodeJWT((char*)jwt.c_str(), (char*)jsonPayload, payloadLength)) {
    
      Serial.print("ArduinoJWT.cpp jsonPayload:");
      
      // Comment !!!!!!! jsonPayload doesn't contain the Payload, but the Payload can be printed char by char...
      for(int i=0;i<payloadLength;i++){
        Serial.print(char(jsonPayload[i]));
      }
      // Comment !!!!!!! 
      // Comment to avoid arduino restart: payload = String(jsonPayload); // odkomentováno, jinak se to sekne
      
      return true;
      
    }
  }
  return false;
}
tomasp
Příspěvky: 55
Registrován: 15 dub 2014, 23:01

Re: ArduinoJWT knihovna

Příspěvek od tomasp »

Ahoj,
v otázce píšeš, že
ale nedaří se mi uložit proměnnou a vrátit ji funkcí - je prázdná
, ale v kódu máš u toho řádku poznámku, že se to sekne (což je rozdíl).

Počítám, že se to nejspíš sekne, a pak bych měl podezření, že tomu poli znaků, které se převádí na String, chybí ukončovací znak '\0'. Takže nastane "nekonečný cyklus", ta funkce neví, kdy má s iterací pole přestat.

Takže by ses měl přesvědčit, že pole získané funcí decodeJWT(...) je skutečně zakončeno tím '\0'.

V tomto případě je mi také podezřelé, že tady na fóru v kódu máš

Kód: Vybrat vše

int payloadLength = getJWTPayloadLength(jwt);
a na gitlabu je pro soubor ArduinoJWT.cpp

Kód: Vybrat vše

int payloadLength = getJWTPayloadLength(jwt)-1;
Dokonce bych osobně řekl, že oboje není správně a mělo by tam být +1
int payloadLength = getJWTPayloadLength(jwt)+1;
Tím vynikne místo navíc pro '\0', která se tam bude "sama od sebe", nebo ho tam můžeš ručně přidat, ale to asi nebude nutné. Prostě bych to pole prodloužil o jeden znak a přesvědčil bych se, že po naplnění končí '\0'.

Tom
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

Re: ArduinoJWT knihovna

Příspěvek od hubacekp »

Ta část getJWTPayloadLength(jwt)-1; je pozůstatek z mnoha mých pokusů. Nemá to tam být.
V jiné části knihovny se pracuje s polem správně s tou +1.

děkuji. udělám si výpis pole v dec a uvidím.
DavidO
Příspěvky: 1133
Registrován: 01 kvě 2013, 21:27

Re: ArduinoJWT knihovna

Příspěvek od DavidO »

Není String jako string, v tom to celé bude.
C string je posloupnost znaků ukončená znakem s kódem 0, zabírá místo tolik, kolik je znaků plus ta nula na konci. String je třída, kde uložení řetězce není přesně specifikováno a zároveň v té třídě je hafo funkcí na nejrůznější divná "intuitivní" použití. Na "PC-like" platformách se o to nějak postará překladač + běhová podpora, kdy se to obvykle díky programátorově nešikovnosti spoustakrát kopíruje po paměti sem a tam, ale na malých jako je AVR to není až tak jednoduché - málo výkonu, málo paměti... jako konkrétně to je na Arduinu z hlavy nevím, mohl bych se podívat na konkrétní implementaci třídy String, ale principiálně tam je problém s více různými paměťmi, protože "adresa" není jednoznačné určení (může to být adresa v programové paměti, v SRAM, v EEPROM) a v lokalitě proměnných (např. když máš lokální proměnnou jako pole ale chceš to pole pak vrátit volající funkci, to je pak blbé). V tomhle příkladě mi to připadá, že decodeJWT chce C-string, který ale získáš z třídy String její metodou na získání C-stringu, ta funkce pak vrátí opět C-string, který ale chceš překabátit do Stringu a něco s ním dál dělat, třeba ho poslat pomocí println. To je několikeré převádění sem tam. Lepší by bylo držet pořád jednu variantu, asi nejspíš proměnnou typu pole znaků (tj. C-string) a s tím dělat pořád. Od získání při komunikaci, přes dekódování až po finální zpracování.
Naposledy upravil(a) DavidO dne 24 lis 2017, 19:14, celkem upraveno 1 x.
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
DavidO
Příspěvky: 1133
Registrován: 01 kvě 2013, 21:27

Re: ArduinoJWT knihovna

Příspěvek od DavidO »

+1 nebo -1 je typický problém.
NUTNÉ je uvědomit si, co máš za data a co znamenají. Problém s "délkou řetězce" je, jestli myslíš "počet písmen" nebo "co to zabírá v paměti", protože v případě obyčejného C-strinu se to liší o tu 1 koncovou nulu, ale v případě dnes moderních národních abeced to taky může znamenat rozdíl násobný (jeden znak v Unicode zabírá 1 - 4 byty a ještě tam může být ta koncová nula).

Tome: Co se týče zpracování řetězce, u kterého někdo zapomněl uložit tu 0, tak to pak "jede v paměti dál a dál, až to na nějakou nulu narazí". Dřív nebo pozdějc to nastane, rozhodně ne "nekonečný cyklus", prostě jede až dojede. Ta nula v paměti vždycky někde je. Na rozdíl od PC tady není žádná kontrola přístupu, takže to sebou nemusí švihnout vůbec, akorát to bude dělat blbosti.
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
DavidO
Příspěvky: 1133
Registrován: 01 kvě 2013, 21:27

Re: ArduinoJWT knihovna

Příspěvek od DavidO »

Jo a samozřejmě - můžem na to mrknout zítra na Robodoupěti
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
tomasp
Příspěvky: 55
Registrován: 15 dub 2014, 23:01

Re: ArduinoJWT knihovna

Příspěvek od tomasp »

DavidO píše: 24 lis 2017, 19:13 Tome: Co se týče zpracování řetězce, u kterého někdo zapomněl uložit tu 0, tak to pak "jede v paměti dál a dál, až to na nějakou nulu narazí". Dřív nebo pozdějc to nastane, rozhodně ne "nekonečný cyklus", prostě jede až dojede. Ta nula v paměti vždycky někde je. Na rozdíl od PC tady není žádná kontrola přístupu, takže to sebou nemusí švihnout vůbec, akorát to bude dělat blbosti.
Jojo, toho jsem si byl vědom, když jsem to psal, proto ty uvozovky. Akorát jsem měl dojem, že moje odpověď nekontrolovatelně boptná, tak jsem se rozhodl napsat to jednoduše, krátce ... a špatně :)
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

Re: ArduinoJWT knihovna

Příspěvek od hubacekp »

děkuji vřele za náměty.
Na robodoupě se bohužel nedostanu, protože jsem vyfasoval děti a jedu s nimi na víkend pryč...
hubacekp
Příspěvky: 259
Registrován: 24 úno 2013, 13:40

Re: ArduinoJWT knihovna

Příspěvek od hubacekp »

Tak jsem se na to podíval podle vašich připomínek a na konci řetězce nula byla.
Zkoušel jsem to horem spodem a nakonec mě napadlo vyzkoušet následující:
původní payload = String(jsonPayload); jsem upravil na payload = jsonPayload;
A bylo vymalováno, funguje to :-)

Zkusím se ještě podívat na volání funkce, jestli mám funkci volat s testDecoded jako String, nebo jiným typem.

Kód: Vybrat vše

String testDecoded = "x";
for( int i=0 ; i < message.length() ; i++) testDecoded[i] += 'x';
boolean decodedToken = jwt.decodeJWT(encodedJWT, testDecoded);
Odpovědět