HMAC-sigill som aldrig godkänns (PHP)

Permalänk

HMAC-sigill som aldrig godkänns (PHP)

Jag tror att jag behöver andra ögon på det här problem.

Så här är läget:
Vi har ett fixat ett eget system för autogirohantering som bättre passar oss än de generella affärssystemen. Den biten funkar utmärkt när vi kört ett längre test med manuell uppladdning till banken via internetbanken.
Så nästa steg i projektet var att automatisera överföringen fram och tillbaka med SFTP och allt där funkar också utom en detalj, HMAC-sigillet.

Jag håller på att bli tokig av leta information över vad jag kan ha gjort för fel och i just denna fråga är inte Bankgirot så behjälpligt heller. Så jag får testa mig fram och invänta svar på varje enskild testfil som kan ta evigheter och oftast innehåller följande:

"Anledning till att filen har makulerats: Filen är sigillerat med rätt nyckel men något i filen stör beräkningen av sigillet."

Filens sigill skapas såhär:

Citat:

$test = "00220322HMAC
0120220317AUTOGIRO 2222220001111111
0300011111110000000003074887
0300011111110000000009198973 ";

$key = "1234567890ABCDEF1234567890ABCDEF";
$key = hex2bin($key);

file_put_contents('BFEP.IAGZZ.K0222222.D220322T175608.txt', $test);

$kvv = strtoupper(hash_hmac('sha256', '00000000', $key));
$kvv = substr($kvv, 0, 32);

$sig = strtoupper(hash_hmac('sha256', $test, $key));
$sig = substr($sig, 0, 32);

$string = "99" . date('ymd') . $kvv . $sig . addSpace(8);

file_put_contents('BFEP.IAGZZ.K0222222.D220322T175608.txt', $string, FILE_APPEND);

addSpace = funktion för att fylla ut rader med mellanslang
$kvv = verifiering att rätt nyckel används med godkänt resultat från Bankgirot
$sig = sigillet för innehållet som då inte är godkänt
$string = datum, verifiering och sigill ihopslaget

Referenserna jag använt mig av för detta:
https://www.bankgirot.se/globalassets/dokument/tekniska-manua...
https://www.bankgirot.se/globalassets/dokument/tekniska-manua...

Jag har testat med onlinebaserade HMAC-generatorer och får exakt samma resultat som det som skapas från PHP:s hash_hmac() (eller hash_hmac_file() ) med testnyckeln.
Jag har testat att använda radslut från Linux och Windows samt med och utan CRLF.
Jag har frågat Bankgirot om exempelfiler som har ett korrekt uträknat sigill men det är den enda typen av exempelfiler de inte har.

Det ska vara en massa tomrum och sådant i filen då alla rader ska vara 80 tecken långa och just denna bit har jag dubbelkollat att det inte är för mycket eller för lite mellanslag någonstans (vilket jag ser försvinner här, men det spelar mindre roll).

Vi kör med en LAMP-server och Swedbanks SFTP-som detta skickas till misstänker jag kör Windows då den saknar Rsync för överföringen men att SCP funkar.
Testöverföringarna har nu gjorts med Filezilla.
Filer som förs över försvinner efter relativt kort stund men jag har inte kunnat se något uppenbart som Filezilla skulle kunna ha gjort under överföringen. När det går på automatik så förs det över via SCP.

Nu är väl detta långt nog men jag försöker få med så mycket information som möjligt. Finns det något uppenbart jag missat eller har någon kanske till och med pyssla med HMAC-sigill för överföring till banken?

Tacksam för svar!

Permalänk
Medlem
Skrivet av Squall Leonhart:

Jag tror att jag behöver andra ögon på det här problem.

Så här är läget:
Vi har ett fixat ett eget system för autogirohantering som bättre passar oss än de generella affärssystemen. Den biten funkar utmärkt när vi kört ett längre test med manuell uppladdning till banken via internetbanken.
Så nästa steg i projektet var att automatisera överföringen fram och tillbaka med SFTP och allt där funkar också utom en detalj, HMAC-sigillet.

Jag håller på att bli tokig av leta information över vad jag kan ha gjort för fel och i just denna fråga är inte Bankgirot så behjälpligt heller. Så jag får testa mig fram och invänta svar på varje enskild testfil som kan ta evigheter och oftast innehåller följande:

"Anledning till att filen har makulerats: Filen är sigillerat med rätt nyckel men något i filen stör beräkningen av sigillet."

Filens sigill skapas såhär:

addSpace = funktion för att fylla ut rader med mellanslang
$kvv = verifiering att rätt nyckel används med godkänt resultat från Bankgirot
$sig = sigillet för innehållet som då inte är godkänt
$string = datum, verifiering och sigill ihopslaget

Referenserna jag använt mig av för detta:
https://www.bankgirot.se/globalassets/dokument/tekniska-manua...
https://www.bankgirot.se/globalassets/dokument/tekniska-manua...

Jag har testat med onlinebaserade HMAC-generatorer och får exakt samma resultat som det som skapas från PHP:s hash_hmac() (eller hash_hmac_file() ) med testnyckeln.
Jag har testat att använda radslut från Linux och Windows samt med och utan CRLF.
Jag har frågat Bankgirot om exempelfiler som har ett korrekt uträknat sigill men det är den enda typen av exempelfiler de inte har.

Det ska vara en massa tomrum och sådant i filen då alla rader ska vara 80 tecken långa och just denna bit har jag dubbelkollat att det inte är för mycket eller för lite mellanslag någonstans (vilket jag ser försvinner här, men det spelar mindre roll).

Vi kör med en LAMP-server och Swedbanks SFTP-som detta skickas till misstänker jag kör Windows då den saknar Rsync för överföringen men att SCP funkar.
Testöverföringarna har nu gjorts med Filezilla.
Filer som förs över försvinner efter relativt kort stund men jag har inte kunnat se något uppenbart som Filezilla skulle kunna ha gjort under överföringen. När det går på automatik så förs det över via SCP.

Nu är väl detta långt nog men jag försöker få med så mycket information som möjligt. Finns det något uppenbart jag missat eller har någon kanske till och med pyssla med HMAC-sigill för överföring till banken?

Tacksam för svar!

Detta ur hmac_tamperprotection_technicalmanual_en.pdf:

"When calculating the MAC;
• The entire file including the Seal Opening record (TK 00), must be
processed in the algorithm. The Tamper Protection record (TK 99) however,
is used to store the calculated MAC and, therefore, should not be included in
the calculation.
• If end-of-line characters are used in the file (LF, CRLF, Carriage Return Line
Feed), these characters should not be included in the calculation.
• Note that the file data should be normalised before the calculation of the
MAC.
• Note that only the first 80 characters of the Seal Opening record should be
included in the seal calculation, regardless of actual size. Particularly
important when validating seal on received files."

nyrader ska alltså inte vara med när du beräknar din MAC...?

Visa signatur

Desktop: Ryzen 5800X3D || MSI X570S Edge Max Wifi || Sapphire Pulse RX 7900 XTX || Gskill Trident Z 3600 64GB || Kingston KC3000 2TB || Samsung 970 EVO Plus 2TB || Samsung 960 Pro 1TB || Fractal Torrent || Asus PG42UQ 4K OLED
Proxmox server: Ryzen 5900X || Asrock Rack X570D4I-2T || Kingston 64GB ECC || WD Red SN700 1TB || Blandning av WD Red / Seagate Ironwolf för lagring || Fractal Node 304

Permalänk
Medlem

Tvåa på bollen

Av den engelska referensen framgår att du inte ska ha med radslut i HMAC-indatat. Jag ser inte hantering för det i din kod, men du kanske helt tagit bort radslut.

Jag ser inte heller hanteringen av svenska tecken , ”normalization”, men det ska ju inte vara ett problem eftersom du inte har några i din nuvarande testdata. Oavsett så bör du vara explicit med teckenkodningen när du skriver filen, ifall det där är PHP:iska för att skriva en textfil.

Avslutningsvis så tycker specen att du ska behandla indata som binärdata. Oklart för mig om det spelar roll jämfört med vad du gör.

Permalänk

Normaliseringen har jag löst genom att ta bort alla möjligheter att ha ÅÄÖ (eller andra specialtecken). Så funktionen
mb_check_encoding() rapporterar ASCII, vilket jag tolkar som att det ska vara rätt. Stoppar jag in ett Ä så rapporterar den funktionen UTF-8.

Jag kanske feltolkar informationen, men för mig ser det ut som att när en fil skapas via PHP så finns det ingen CRLF i den om inte PHP_EOL anges.
Skapar jag en fil och testar med cat -A på den så ser resultatet ut såhär:
https://tenton.se/graphic/Screenshot_20220323_142444.png
$ = Linux-radslut
Det borde vara ett $ på sista raden också om CRLF skulle ha funnits.

Tack i alla fall för förslag

Permalänk
Medlem
Skrivet av Squall Leonhart:

Normaliseringen har jag löst genom att ta bort alla möjligheter att ha ÅÄÖ (eller andra specialtecken). Så funktionen
mb_check_encoding() rapporterar ASCII, vilket jag tolkar som att det ska vara rätt. Stoppar jag in ett Ä så rapporterar den funktionen UTF-8.

Jag kanske feltolkar informationen, men för mig ser det ut som att när en fil skapas via PHP så finns det ingen CRLF i den om inte PHP_EOL anges.
Skapar jag en fil och testar med cat -A på den så ser resultatet ut såhär:
https://tenton.se/graphic/Screenshot_20220323_142444.png
$ = Linux-radslut
Det borde vara ett $ på sista raden också om CRLF skulle ha funnits.

Tack i alla fall för förslag

Om det inte hade funnits några radbrytningar så skulle väl allt ha varit på en rad, alltså finns det åtminstone LF, kanske även CR?

Jag tycker allt tyder på att felet ligger i att du inte filtrerar bort CR och/eller LF när du skapar MACen

Visa signatur

Desktop: Ryzen 5800X3D || MSI X570S Edge Max Wifi || Sapphire Pulse RX 7900 XTX || Gskill Trident Z 3600 64GB || Kingston KC3000 2TB || Samsung 970 EVO Plus 2TB || Samsung 960 Pro 1TB || Fractal Torrent || Asus PG42UQ 4K OLED
Proxmox server: Ryzen 5900X || Asrock Rack X570D4I-2T || Kingston 64GB ECC || WD Red SN700 1TB || Blandning av WD Red / Seagate Ironwolf för lagring || Fractal Node 304

Permalänk
Skrivet av evil penguin:

Om det inte hade funnits några radbrytningar så skulle väl allt ha varit på en rad, alltså finns det åtminstone LF, kanske även CR?

Jag tycker allt tyder på att felet ligger i att du inte filtrerar bort CR och/eller LF när du skapar MACen

Jag tackar och bockar!
Jag hade misstolkat den biten och tog bara bort den sista radbrytningen. Då resten av filens innehåll var godkänd av banken så hade jag fått det till att övriga radbrytningar kunde vara kvar men att det inte fick finnas en "tom" radbrytning (som det exempelvis alltid blir när man skapar en textfil i Linux).

Fixade det med:

$test = str_replace (array("\r\n", "\n", "\r"), '', $test);

Permalänk
Medlem
Skrivet av Squall Leonhart:

Jag tackar och bockar!
Jag hade misstolkat den biten och tog bara bort den sista radbrytningen. Då resten av filens innehåll var godkänd av banken så hade jag fått det till att övriga radbrytningar kunde vara kvar men att det inte fick finnas en "tom" radbrytning (som det exempelvis alltid blir när man skapar en textfil i Linux).

Fixade det med:

$test = str_replace (array("\r\n", "\n", "\r"), '', $test);

Ja, precis. Som jag förstod det så får radbrytningar finnas i filen, men inte i underlaget till MACen

Visa signatur

Desktop: Ryzen 5800X3D || MSI X570S Edge Max Wifi || Sapphire Pulse RX 7900 XTX || Gskill Trident Z 3600 64GB || Kingston KC3000 2TB || Samsung 970 EVO Plus 2TB || Samsung 960 Pro 1TB || Fractal Torrent || Asus PG42UQ 4K OLED
Proxmox server: Ryzen 5900X || Asrock Rack X570D4I-2T || Kingston 64GB ECC || WD Red SN700 1TB || Blandning av WD Red / Seagate Ironwolf för lagring || Fractal Node 304

Permalänk
Medlem
Skrivet av Squall Leonhart:

Jag tackar och bockar!
Jag hade misstolkat den biten och tog bara bort den sista radbrytningen. Då resten av filens innehåll var godkänd av banken så hade jag fått det till att övriga radbrytningar kunde vara kvar men att det inte fick finnas en "tom" radbrytning (som det exempelvis alltid blir när man skapar en textfil i Linux).

Fixade det med:

$test = str_replace (array("\r\n", "\n", "\r"), '', $test);

Borde räcka med $test = str_replace (array("\n", "\r"), '', $test); ?

Nu var det 20år sedan jag sysslade med PHP

Visa signatur

Hur många datorer är för många?