base64 encode probléma?

Fórumok

Szükségem van a K&H bank új (Csehországba kiszervezett, és ezért újfent megbuherált) payment gateway rendszeréhez egy privát kulcs file base64 elkódolására, amit többféleképpen is megcsináltam az eredmény ellenőrzéséhez (KDE Neon linuxot használok):

base64 rsa.key > output.key
base64url rsa.key > output.key
openssl enc -a -in rsa.key
online
(https://www.base64encode.org)

Az eredmény mindig megegyezett, tehát úgy gondolom, hogy a BASE64 kódolással minden rendben lehet.

A kulcsokat a K&H Bank erre készített oldalán állítottam elő a szükséges adatokból, és a public key onnan is került feltöltésre automatikusan.

Mindezek ellenére, amikor leellenőrzöm a kulcsot a bank erre való oldalán, akkor az "Invalid request: INVALID_PARAM: Invalid length of signature parameter" hibaüzenetet kapom.

A lekérdezés egyébként ez:

curl -v -X POST https://api.sandbox.khpos.hu/api/v1.0/echo -H "Content-Type: application/json" -d '{"merchantId":"vPOS_ID","dttm":"date_time","signature":"encoded_in_BASE64"}'

Szerintetek én kefélek el valamit az encode során? Másképpen kellene csinálni? Nem  tudom pl. számít-e az, hogy a key fájlban van két plusz sor:

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

Ez a két sor vajon része a kulcsnak, vagy a kódolás során ezeket figyelmen kívül hagyja a rendszer.
(Mert ha pl. nem a fájlt, hanem csak magát a kulcsot olvastatom be a programokkal kódolásra, akkor más lesz az encode eredménye, de az én hibaüzenetem nem változik: Invalid length of signature parameter)

Hozzászólások

Ezt minek base64 enkódolni egyáltalán? Ez a formátum már önmagában base64

"signature":"base64-encoded-signature-of-payment-request"  (innen)

 

miért küldenél el base64 kódolt _privát_kulcsot_?

 

TEXT_TO_SIGN = ...payment request payload | karakterrel szeparálva...
signature = BASE64_ENCODE(RSA_SIGN(TEXT_TO_SIGN))

Arra gondol, hogy a gpg armoros pem kulcsok eleve base64-ben vannak.

https://github.com/khpos/Payment-gateway_HU/wiki/Request-Signing-and-Re…

Ez alapján az echoba neked nem a kulcsot kell beletenni, hanem kell generálni a payloadból egy stringet, azt kell aláírni a kapott kulccsal, majd base64 encodeolni.

Szerk: félrebeszeltem, épp vmi gpgt baszogattam 5 perccel előtte 

\n vs. \r\n kulonbseg esetleg? Az is +1 byte soronkent

A strange game. The only winning move is not to play. How about a nice game of chess?

Kicsit pongyolán van megfogalmazva a kérdés, de ahogy Friczy is írta, ha a file úgy kezdődik, hogy "-----BEGIN RSA PRIVATE KEY-----", akkor az már eleve Base64 ASCII formátum (openssl terminológiában ez a PEM formátum).  Gyakran - leginkább Java technológiát használó alkalmazások - használnak még bináris (DER) formátumot is, "openssl x509" commanddal gyönyörűen lehet oda-vissza konvertálni PEM és DER között.  Mivel a PEM formátum base64 encode-olásának sok értelme nincs, azt elképzelhetőnek tartom, hogy ők a DER formátumú file base64 encode-olt változatát kérnék felpostolni.

Ami nekem amúgy gyanús, hogy miért kellene privát kulcsot bárhova feltöltened?  A privát kulcs lényege, hogy privát.  A fenti curl command is signature-ként hivatkozik ott az adatra, ami ezek alapján inkább valami olyan aláírás lenne, amihez a privát kulcsodat helyben használod. (pl. "openssl dgst -sign" commanddal).  Ha mesélsz bővebben a folyamatról és hogy ez mihez kell, akkor tud itt neked bárki érdemben segíteni.  +1: ha ez nem egy nagyon-nagyon teszt rendszer, akkor amint a fenti online oldalra (base64encode.org) submitoltad a privát kulcsodat, azonnal cseréld is le a kulcspárodat.  Magamat ismétlem, de a privát kulcs lényege, hogy privát.

Csinálsz egyáltalán RSA aláírást, vagy magát a kulcsot küldöd el?

Sértésnek veszed, de valóban el kellene gondolkodni. Vagy legalább megérteni, hogy itt mit szeretne kapni a túloldal. Mert nem egy privát kulcsot.

A postod alapján virtual POS funkcionalitással dolgozol, ami azért eléggé feleőségteljes dolog (szerintem), de úgy, hogy nem érted a privát aláírókulcs és az ezzel aláírt majd ezután BASE64 kódolt signature között a különbséget...

De most a privát kulcsot küldöd el nekik? Ott aláírást kell küldened. Privát kulcsot soha nem küldünk senkinek. Azért "privát".

Pontosan úgy van, ahogy írtad, nem nekem kellene ezt csinálnom.

Az a helyzet, hogy én készítettem az oldalt, ahol erre szükség lenne, így az előző K&H payment gateway illesztést is én írtam hozzá (PHP-ben), ami rendben működik is 4-5 éve. (Ez viszont megszűnik működni szeptember 30. után.)

Most viszont, ahogy elolvastam az új illesztés dokumentációját – ismerve a korlátaimat – azonnal tudtam, hogy nem én vagyok erre a megfelelő ember, így nem is vállaltam el. De mivel az oldalt üzemeltető alapítvány vezetője kétségbe esett, hogy akkor most mi lesz, gondoltam, hogy teszek egy próbát, de nem kellett volna, ahogy azt a hozzászólások is mutatják. Azonnal szembesültem a fogalmatlanságommal. Mentségemre szóljon, hogy minden a Sandbox felületen történt.

Sajnos nem ismerek senkit akit megkérdezhetnék, hogy elvállalná-e ezt a munkát. Korom miatt több mint 4 éve kiestem a "szakmából".

Fentebb ketten is linkeltük neked a doksi erre vonatkozó részét. Az aláírandó adat előállításához az üzenet elemeinek értékit kell  az endpoint specifikációnak megfelelő sorrendben összefűzni | karakterekkel elválasztva egy stringbe. Az echo esetén ez (a konrét doksiból példa):

TEXT_TO_SIGN = "M1MIPS0000|20220125131615"

a merchantId és a dttm értékek a requestből.

Ezt az általad használt nyelven alá kéne írni sslel. A Technikai GYíKban vannak példák a kulcs betöltésére és az aláírás hogyanjára néhány nyelven, de a gugli első találatai is segíteni fognak. Ha kézzel akarod ezt vmi ilyesmi kell: `openssl dgst -sign private_key_file -sha256 -sigopt rsa_padding_mode:pss -out output_file input_file`

Ez után ezt kell base64 encodeolni, és betenni a signaturebe.

 

TEXT_TO_SIGN

Offtopik, de...

TEXT_TO_SIGN = "M1MIPS0000|5547|20220125131559|payment|card|123400|HUF|true|https://shop.example.com/return|POST|Wireless headphones|1|123400|Shipping|1|0|DPL|Jan Novák|jan.novak@example.com|+420.800300300|2022-01-12T12:10:37+01:00|2022-01-15T15:10:12+01:00|account|2022-01-25T13:10:03+01:00|purchase|now|shipping|1|true|Karlova 1|Praha|11000|CZE|some-base64-encoded-merchant-data|cs"

Egy nested dictionary strukturat ilyen modon alairatni, hat kurva kemeny, nem tudom, mire gondolt itt a kolto, vagy hogy gondolt-e egyaltalan barmire, azon kivul, hogy milyen kozel van a hetvege, es jo lenne mar befejezni ezt a feature-t.

Ja, hat mindegy, nem nekem faj, csak erdekes. Az utokornak, hogy mirol beszelek: JSON RFC

An object is an unordered collection of zero or more name/value
   pairs, where a name is a string and a value is a string, number,
   boolean, null, object, or array.

   An array is an ordered sequence of zero or more values.

==> arra epiteni az alairast, hogy a key-value parokat a kepernyon valo megjelenes sorrendjeben beirod egy sorba, rossz otlet.

Fentebb írtam, hogy pár helyen nem csak jsonban jöhet, illetve a jsonnak van egy ebből a szempontból olyan kellemetlen tulajdonsága, hogy byteok szintjén nem garantált, hogy egy adatnak egy féle valid reprezentációja van (ugye van benne nem szignifikáns whitespace), szóval nem nagyon tudod megcsinálni azt, hogy a kapott értékből kiveszed az aláírást, és a maradékot újra serializálod jsonba, és ellenőrzöl (pedig ha az aláírás is ebben a jsonben van, akkor az nem lehet része az aláírt adatnak nyilván). Illetve hát ez esetben a sorrend lényegtelensége is problémás. Szóval, azt máshol kell vinni, ha az egész jsont alá akarod írni.

Oh, ezzel nem akartam borzolni a kedélyeket, nekem is az volt az első gondolatom, hogy nem tudom, mire gondolt a költő (vagy hát de, csak arra munka közben nem illik), de azért az igazság az, hogy nem teljesen alaptalan.

A legvalidabb indok, hogy nem csak egy serialziációs formátumot támogatnak (a jsont), hanem bizonyos requesteknél a GET nek urllel is meg lehet ezeket adni, pl az echot is ér így: 

curl -v -X GET https://api.khpos.hu/api/v1.0/echo/M1MIPS0000/20220125133015/base64-encoded-request-signature

Én szerintem simán ezeket nem hagynám*, egységesen json, írd alá az egész istenverését egyben, aztán rakd bele a signaturet egy headerbe (query paraméterbe, ha nagyon muszáj), de gondolom a random webframeworkben nem trivi a raw contenthez hozzáférni :)

* ez az api egyébként se valami szép, a keveredő methodokkal (szerencsés név ez egy HTTP APIn) meg paraméterekkel, a kedvenc részem azt hiszem az, amikor egy ugyanilyen signózott lófaszt kell kötelezően a user browseréből küldeni.

Szerkesztve: 2023. 09. 08., p – 11:57

Mivel ez a K&H egyik szolgáltatása, gondolom van mellé support is, illetve van dokumentáció... Ott megnézted/kérdezted (vagy aki nálatok a bank felé megadott kontakt, az megnézte/kérdezte) már?

Igen, nézem a kézikönyvet, de az aláírás / hitelesítés eljárást a fentiek szerint sajnos nem értem.

Az ügyfélszolgálattal leveleztem már többször is, de az első probléma, amibe belefutottam (és utána ezzel két napig el is voltunk), hogy a kézikönyvben a curl lekérdezés példájában egy space karakter hiba van. Ők így írják:

    curl -v -X POST https://api.sandbox.khpos.hu/api/v1.0/echo -H "Content-Type:application/json"

és én ezt használtam, de nem működött. Helyesen viszont így van:

    curl -v -X POST https://api.sandbox.khpos.hu/api/v1.0/echo -H "Content-Type: application/json"

Ezt az aláírási problémát már fel sem vetettem nekik, és utólag nézve szerintem ez így is volt helyes, hiszen ezt a problémát nekem kellene megoldani...

(Ami azt illeti, az előző, régi illesztéshez elég jó példák voltak leírva a kézikönyvben, ott viszonylag könnyen boldogultam.)

Nyilván nem egy rettentő bonyolult dolog, de azért, ha én lennék döntési pozícióban, akkor megfontolnám, hogy ha ezt a nem túl bonyolult fejlesztést (be kell wrappelni azokat a methodokat vmi importálhatóba) bevállalom, akkor:

  • kicsit nyugodtabban alhatok, hogy a kliens oldalon kevesebb böszmeség történik (főleg, ha írok valamit arról is, hogy arra a privát kulcsra vigyázni kéne)
  • kevesebb baja lesz a supportnak
  • könnyebben tudok változtatni
  • ha még esetleg bevállalom, hogy az importálható mondjuk az elterjedtebb commerce cuccokba is megvan (mittomén woocommerce, nem tudom mik mennek, nem mozgok benne), akkor a leendő ügyfeleimnek tudom mondani, hogy nem azzal fog kezdődni, hogy a fejlesztője kiszámláz 1-2 nap munkadíjat a fejlesztésre (rosszabb esetben túr valakit, mert nem ért ehhez), hanem "fel kell tenni a plugint, azt jóidő", szóval még az is lehet, hogy könnyebben adom el a cuccom?

Szinte mindig szoktak adni példakódot php-ban és java-ban.

Egyébként bankok pont leszarják, hogy mennyi meló lefejleszteni. Van több cég is amin keresztül több banki fizetést is tudsz használni, minimál fejlesztői tudás nélkül. Nyilván pénzé'.

Barion speciel ad lib-eket is, igaz nem bank, de mégis fizetési megoldás. Sőt a legtöbb "nem bank" gateway ad.

Egyébként bankok pont leszarják, hogy mennyi meló lefejleszteni. Van több cég is amin keresztül több banki fizetést is tudsz használni, minimál fejlesztői tudás nélkül. Nyilván pénzé'.

Én értem, meanwhile meg az van, hogy ha én pénzt akarnék keresni, akkor lehet igyekeznék kiszolgálni az igényeket, hogy legyenek ügyfeleim. Most a poén kedvéért megnéztem, a kh payment gatewayre és hasonló szavakra random istenverte doksik deeplinkjét adja a kh oldaláról. A simple kb az első találatra ad egy oldalt, ahol van egy vödör partner, akihez lehet menni kulcsrakész megoldásért, össze vannak szedve a doksik (ránézésre úgy egy nagyságrenddel tisztességesebb, mint ez az izé a githubon), példakódokkal, és nahát, php sdk-val. Jé, kin keresztül lehet kb. a magyar internet legnagyobb részén fizetni?

Én értem, hogy kis cégként gondolkozol, de a bank nem kicsi. Ahogy mondom, pont leszarja. Nem érdekli, hogy egy kis ügyfél nem megy hozzá mert nem tetszik neki a rendszer.

Nagyobb cégekért hidd el, hogy tepernek, csak te azt nem látod. (tapasztalat, KH és OTP terén is)

Egyébként gyakori, hogy az sdk-kat, doksikat nem tetszik nyilvánossá. OTP-nek volt alapból nyilvánisan használható, letölthető. Lehet, hogy kissé szar volt, de legaláb ott volt és ki lehetett gányolni, volt benne komplett példatár is php-ban.

KH-nál tuti csak külön kérésre küldték el a kódokat, de ahogy írtam máshol, rém egyszerű volt.

CIB-nél se láttam sehol publikus infókat, oda is fejlesztettem régen fizetést, ők is külön küldték, amúgy az is zsír egyszerű volt.

Barion jól dokumentált, azzal is dolgoztam, ők szépen csinálják, még facebook oldaluk is van ahol segítenek.

Ha értesz hozzá, nincs gond egyikkel se, tényleg. Persze igazat adok, hogy sokkal korrektebb és szebb, ha oda van toszta egy github rendes readme-val.

Én értem, hogy kis cégként gondolkozol, de a bank nem kicsi. Ahogy mondom, pont leszarja. Nem érdekli, hogy egy kis ügyfél nem megy hozzá mert nem tetszik neki a rendszer.

Gondolkozik a fene, kb 20 éve enterspájz környezetben/oda való dolgokon dolgozom. Ettól még lehet az a véleményem, hogy itt segít az üf kör építésnek, ha tisztességesen, és kis bekerülési költséggel integrálható, mert nem elhanyagolható piac itt a kicsi szereplők sem. Mármint komolyan, ehhez az izéhez mennyi lehet egy tisztességes plugint összerakni? 1-2 sprintből vidáman le lehet hozni. (És persze simán lehet tudatos üzleti döntés, hogy nem target, nem foglalkoznak vele, de az, hogy ráguglizva nincs egy normális landing page, a weboldal irányából nincs egy 1 perc alatt megtalálható menüpont arra, ami létezik, az simán csak nettó balfékség.)

Igen, később számomra is kiderült, hogy mi a szitu: https://hup.hu/comment/2962903#comment-2962903 sajnos ha nincs valóban képben se ő, se az, aki a rendszert felépítette/üzemelteti - pl. abban, hogy a privát kulcsot hogyan kéne tárolni/kezelni/védeni - akkor khm. előfordulhatnak durva gubancok...

Egy alternativ javaslat, ami kevesebb szaktudással is bevezethető: KH helyett valamelyik Stripe fizetési megoldás.