NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Jak zavolat funkci pro HEX zobrazení výsledku HMAC_SHA1 hashe ?

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Caster
Člen
Avatar
Caster:7.12.2022 22:47

Na Githubu jsem našel program pro výpočet HMAC_SHA1, který funguje.

Výsledek je 0xeffcdf6ae5eb2fa2d274­16d5f184df9c259a7c79 viz Test Cases for HMAC-SHA-1

Zkusil jsem: K souborům HMAC_SHA1.cpp, HMAC_SHA1.h, SHA1.cpp a SHA1.h z adresáře twitcurl/libtwit­curl/ (pro kompilaci v C++ VS2022) jsem přidal vlastní Main.cpp:

#include <iostream>

#include "SHA1.h"
#include "HMAC_SHA1.h"


BYTE klic[] = "Jefe";
BYTE zprava[] = "what do ya want for nothing?";
BYTE result[20];

int main()
{
    CHMAC_SHA1 obj;
    obj.HMAC_SHA1(zprava, 28, klic, 4, result);
    obj.ReportHash((char*)result, 0);
}

Chci docílit: Program v pohodě spočítá HMAC_SHA1, výsledek 20 bytů je uložen v result.

Pomocí "utility" funkce ReportHash viz SHA1.h

        - Made support/compilation of the utility functions (ReportHash
          and HashFile) optional (useful, if bytes count, for example in
          embedded environments)

        // Report functions: as pre-formatted and raw data
#ifdef SHA1_UTILITY_FUNCTIONS
        void ReportHash(char* szReport, unsigned char uReportType = REPORT_HEX);
#endif
        void GetHash(UINT_8* puDest);

chci zobrazit výslednou hash v HEX tvaru. Nevím ale, jak správně zavolat funkci, která má již přednastaven uReportType = REPORT_HEX bez toho, abych jí musel zadávat nějaké další parametry. Předpokládám, že musí jít funkci nějak snadno zavolat, ale netuším jak. Je taky zvláštní, že ji nemusím volat přes druhý objekt třídy CSHA1.

Nyní funkce

bj.ReportHash((char*)result, 0);

spadne na chybu, že hash 20 bytů nyní ukončena 0x00

P.S. Na začátku jsem měl také problém, jak vůbec zavolat funkci HMAC_SHA1. Podle chybové hlášení a rady v jiném případě na stackowerflow jsem musel nejdříve přiřadit třídu CHMAC_SHA1 obj a přes obj. pak volat vlastní funkci.

 
Odpovědět
7.12.2022 22:47
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:7.12.2022 23:48

Podívej se na prefix prvního formálního parametru metody reportHash() třídy CSHA1.

void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX);

To sz je tam důležité, jedná se o Maďarskou notaci a znamená to:
"string of characters terminated by a nul character". Tedy řetezec ukončený nulovým znakem.

Takže nemůžeš předávat čisté result, neboť to obsahuje pouze data bez nul.
Musíš předat data spolu s nulovým znakem.

Argument druhého parametru musí být buď REPORT_HEX nebo REPORT_DIGIT. Parametr má inicializaci, pokud jej neuvedeš. Tedy pokud nezadáš nic bude předávaná hodnota REPORT_HEX.

Nahoru Odpovědět
7.12.2022 23:48
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:8.12.2022 1:35

Díky za vysvětlení. Nedává mi to ale moc smysl. szRport vypadá spíš jako výstupní string, do kterého se bude zapisovat 20 bytů hashe převedených na HEX viz funkce v SHA1.cpp:

#ifdef SHA1_UTILITY_FUNCTIONS
// Get the final hash as a pre-formatted string
void CSHA1::ReportHash(char* szReport, unsigned char uReportType)
{
        unsigned char i;
        char szTemp[16];

        if (szReport == NULL) return;

        if (uReportType == REPORT_HEX)
        {
                sprintf_s(szTemp, "%02X", m_digest[0]);
                strcat_s(szReport, sizeof(szReport), szTemp);

                for (i = 1; i < 20; i++)
                {
                        sprintf_s(szTemp, " %02X", m_digest[i]);
                        strcat_s(szReport, sizeof(szReport), szTemp);
                }
        }
        else if (uReportType == REPORT_DIGIT)
        {
                sprintf_s(szTemp, "%u", m_digest[0]);
                strcat_s(szReport, sizeof(szReport),szTemp);

                for (i = 1; i < 20; i++)
                {
                        sprintf_s(szTemp, " %u", m_digest[i]);
                        strcat_s(szReport, sizeof(szReport), szTemp);
                }
        }
        else strcpy_s(szReport, sizeof(szReport), "Error: Unknown report type!");
}
#endif

Těch 20 bytů hashe se automaticky načítá pomocí m_digest[i]
Nedává mi to vůbec smysl, proč by se pro výpis hashe měl zadávat nějaký string, kam se budou HEX data zapisovat.

RAW výsledek lze také uložit jinam pomocí druhé funkce (bez převodu na ASCII HEX):

// Get the raw message digest
void CSHA1::GetHash(UINT_8* puDest)
{
        memcpy(puDest, m_digest, 20);
}

"Utility" funkce mi připadá jako naprosto složitý nesmysl. Data jsou po výpočtu uložena v poli result (20 byte) a stačí je jen převést na HEX a vypsat.

Výpis HEX hodnot jsi mi poradil již v jednom z dřívějších dotazů viz Převod HEX řetězce na pole bytů ;-)

Fakt vůbec nechápu smysluplné použití té utility funkce.

 
Nahoru Odpovědět
8.12.2022 1:35
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:8.12.2022 2:12

Přesně tak. První parametr vyjadřuje ukazatel na pole, na jehož konec se budou přidávat konverovaná data z m_digest. Ta funkce není napsaná dobře, není důvod používat mezibuffer. Použij tu funkci kterou jsem Ti poslal v článku na který se v příspěvku odkazuješ.

Nahoru Odpovědět
8.12.2022 2:12
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:8.12.2022 14:18

Že je funkce kostrbatá, je to nejmenší. Ve funkci jsou hlavně chyby.

Secure verze funkce sprintf_s() má prototyp:

int sprintf_s(
   char *buffer,
   size_t sizeOfBuffer,
   const char *format,
   ...
);

ve funkci je ale volána se třemi argumenty, s absencí velikosti bufferu.

Secure verze funkce strcat_s() má následující prototyp:

errno_t strcat_s(
   char *strDestination,
   size_t numberOfElements,
   const char *strSource
);

Ve funkci je ale druhý argument zjišťován pomocí operátoru preprocesoru sizeof, což je naprostý nesmysl.
Snaha získat velikost objektu postrádá korektnost, neboť pomocí sizeof akorát určí velikost ukazatele nikoli velikost objektu. Výsledkem výrazu sizeof(szReport) bude vždy 4, ne však velikost pole do kterého chce data ukládat.

Nahoru Odpovědět
8.12.2022 14:18
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:8.12.2022 14:41

Díky za upřesnění, pro výpis použiji tvou funkci ;-).

P.S. Pokouším se odhalit, proč mnou naprogramovaná funkce HMAC SHA1 chybně počítá SHA1, pokud je délka zprávy delší než 64 znaků (512 bitů). Pro HMAC (viz implementation) se v kroku 1 doplní klíč nulami na 512 bitů a provede se XOR s 0x36 k tomu se pak v dalším 512 bit bloku přidá message. Podrobně jsem to popsal v jiném fóru.

 
Nahoru Odpovědět
8.12.2022 14:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 6 zpráv z 6.