(focus op een PHP-back-end met MPC, Data Masking, DLP, sterke crypto en robuuste in en uitgaande data beveiliging)
In dit onderzoek brengen we in kaart hoe we moderne beveiligingstechnieken kunnen toepassen in onze eigen PHP-backend. we willen onder meer bekijken hoe multiparty compute, data masking, data loss prevention en sterke cryptografie naadloos samenwerken zonder dat we inleveren op de snelheid van onze transacties, de wettelijke kaders of de groei in gebruikersaantallen. het achterliggende doel is dat al onze gevoelige klantinformatie, van persoonsgegevens tot vermogensposities, te allen tijde beschermd blijft tegen ongewenste inzage, manipulatie of verlies.
In scope
Gevoelige datastromen tussen mobiele apps, onze webportalen, micro backoffice services en backoffice services.
Verwerking en opslag in onze PHP core.
Veilige koppelingen met dataproviders, datanetwerken en externe providers.
Toegang door interne developers en support via veilige omgevingen.
Niet in scope
Webpagina's of CMS-pagina’s.
Derde partij SaaS modules buiten ons beheer.
Volledig anonieme open data die al publiek is.
PSD2 / RTS: sterke klantauthenticatie en secure communication.
AVG/GDPR: dataminimalisatie, rechtmatige verwerking, datalekmeldplicht.
Elk onderdeel krijgt een Go / No Go op basis van: haalbaarheid qua performance, compatibiliteit en security.
Doel Gevoelige berekeningen (bijv. risicoscore) uitvoeren zonder dat één partij alle ruwe data ziet.
Aanpak Proof of concept in PHP. Scenario: bereken gemiddelde fraudekans uit drie bronnen zonder de onderliggende cijfers te delen.
Go = latency < 10.000 ms en identiek resultaat t.o.v. centrale berekening.
Doel gevoelige gegeven afschermen in logs, dev-dumps en supportscreens.
Aanpak Dynamisch vervangen buiten productie (****1234) + statische mask.
Go = 100 % productiedata geanonimiseerd in niet produdctie omgevingen.
Doel: Alle uitgaande bestanden & datapayloads scannen op Persoonlijk identificeerbare informatie (PII).
Aanpak: Alerts naar security kanaal.
Go = geen onbedoelde gevoelige data in files.
Doel Elke endpoint voldoet aan “zero trust”.
Aanpak: logging inclusief userID en IP.
Go = 100 % testcases op succes
Doel Alle gevoelige kolommen zoals persoonsgegevens versleuteld.
Aanpak Encryptie in combinatie met tags voor integriteitscheck.
Go = succesvolle sleutelrotatie zonder dataverlies.
Doel Betrouwbare identiteit voor externe partners en mobiele apps.
Aanpak Per partner een key vault met automatische roll over.
Go = handtekeningcontrole faalt binnen 30s in test.
Doel Snellere en lichtere beveiliging voor mobiele clients.
Aanpak Hybrid schema: eerst ECIES, daarna AES.
Go = handshake < 1000 ms op 3G;
< 1 % onversleutelde PII in test en logbestanden.
< 10s extra latency door encryptielagen op kritieke data.
100 % API calls geauthenticeerd en gelogd met context (user, scope, IP).
Automatische sleutelrotatie binnen 90 dagen zonder uitvaltijd.
Maandelijks securityrapport met audittrails.
Technologie Nieuwe PHP code & key vault.
Team 4 senior PHP developers, 1 project manager
Training Crash-course MPC + ECC voor developers
Geen open findings bij interne pen-test.
Performance < 10 % op gemiddelde transactieketen.
Regelmatige audit-PDF (fintech variant) met handtekening en volledige hash-keten.
Groene vlag van AVG én compliance (PSD2).
Met dit plan zetten we de stap van “security” naar een data architectuur die by design vertrouwelijk, integer en traceerbaar is, precies wat fintech toezichthouders, partners en vooral onze eindgebruikers verwachten.
Partisia is een toonaangevende partij in SMPC-oplossingen.
Hun platform draait volledig in de cloud en biedt beveiligde samenwerkingen tussen organisaties, waarbij data wiskundig wordt verdeeld over meerdere partijen.
Kosten: Start vanaf €5.000 per maand, afhankelijk van verbruik en aantal partijen.
Voordelen:
Zeer veilig voor interbedrijfssamenwerkingen.
Audit-rapporten en governance ingebouwd.
Nadelen:
Volledig SaaS; geen lokale integratie.
Geen PHP SDK, enkel via API’s of C++/Rust-koppelingen.
Hoge latency; niet geschikt voor realtime dataverwerking.
Sharemind biedt MPC als SaaS en on-prem.
Het is één van de meest volwassen SMPC-platforms.
Kosten: Vanaf €3.000 per maand, plus opslag- en compute-kosten.
Voordelen:
Sterke compliance support (GDPR, ISO).
Biedt on-prem variant.
Nadelen:
Geen directe PHP-integratie; alles via APIs of Java/Rust.
Complex setup en beheer.
Hogere latency (10x-20x t.o.v. normale verwerking).
Alle marktpartijen bieden SMPC als dure SaaS-oplossingen zonder PHP-integratie.
De oplossingen zijn te zwaar, te duur en te complex voor onze interne dataflows.
Zelf ontwikkelen in PHP is sneller, goedkoper en realistischer.
Presidio is een opensource project voor PII detectie en masking.
Kosten: Gratis, maar enkel via Python en lastig te integreren in PHP.
Voordelen:
Sterke PII detectie.
Regel-gebaseerde masking.
Nadelen:
Generiek; breekt makkelijk feedformaten.
Niet ontworpen voor PHP.
Hoge overhead als aparte service.
Talend biedt een commerciële DLP en maskingtool.
Kosten: Licenties vanaf €20.000 per jaar.
Voordelen:
Enterprise grade.
Ondersteuning voor meerdere databases en formats.
Nadelen:
SaaS oplossing; geen directe PHP-integratie.
Zware overhead voor simpele maskingbehoeften.
Er zijn tools beschikbaar, maar die zijn generiek en niet PHP native.
Zelf ontwikkelen is goedkoper, preciezer en beter afgestemd op onze behoeften.
Bekende DLP suite die integratie biedt met netwerken, endpoints en cloud.
Kosten: Vanaf €50.000 per jaar.
Voordelen:
Volledige dekking (email, files, cloud).
Goede compliance support.
Nadelen:
Gericht op bedrijfsbrede netwerken, niet applicaties.
Geen integratie met PHP of onze software.
Hoge kosten en complexiteit.
Focus op SaaS en API DLP.
Kosten: Vanaf €30.000 per jaar.
Voordelen:
API DLP mogelijkheden.
Cloudfirst strategie.
Nadelen:
SaaS only.
Geen PHP SDK.
Hoge kosten.
Cloudbased DLP van Microsoft 365.
Kosten: Ingebouwd in Microsoft 365 E5, prijs afhankelijk van volume.
Voordelen:
Koppeling met andere Microsoft-producten.
Sterke compliance.
Nadelen:
Alleen bruikbaar binnen Microsoft-ecosysteem.
Niet geschikt voor PHP applicaties.
Alle oplossingen zijn zwaar, SaaS-gericht en duur.
Voor onze softwareflow is een lichte, PHP gebaseerde module effectiever en goedkoper.
We kunnen er dus beter voor kiezen om dit zelf te gaan ontwikkelen.
Bekendste open-source API Gateway.
Kosten: Gratis opensource; enterprise vanaf €1.500 per maand.
Voordelen:
Plug-ins voor OAuth2, rate limiting.
Community support.
Nadelen:
Extra laag; voegt latency toe.
Licenties per request kunnen snel oplopen.
Complex beheer.
Alternatief voor Kong.
Kosten: Vanaf €500 per maand (self-hosted).
Voordelen:
Makkelijker te beheren dan Kong.
Sterke OAuth2 support.
Nadelen:
Externe laag blijft vereist.
Licentie per gebruiker of API call.
SaaS API Gateway via AWS.
Kosten: €3.50 per miljoen API calls + data egress.
Voordelen:
Volledig schaalbaar.
Integratie met AWS IAM.
Nadelen:
Hogere latency.
Externe afhankelijkheid.
Kosten lopen snel op bij hoge volumes.
Externe API Gateways bieden veel securityfeatures, maar zijn duur, voegen latency toe en passen niet goed bij onze bestaande PHPstack.
Eigen PHP-implementatie (JWT, OAuth2) is sneller en goedkoper.
Standaard beschikbaar in PHP via OpenSSL-extensie.
Kosten: Gratis (onderdeel van PHP).
Voordelen:
Snel en veilig.
Geen extra kosten.
Nadelen:
Key management moet zelf ingericht worden.
Managed key management en encryptie.
Kosten: €1 per 10.000 encrypties + sleutelbeheer.
Voordelen:
Makkelijk sleutelbeheer.
Nadelen:
Elke encryptie is een API-call (latency).
Kosten kunnen hoog worden bij veel encrypties.
Gebruik OpenSSL in PHP is snel, veilig en zonder extra kosten. Geen reden om naar SaaS te gaan.
RSA is direct via OpenSSL in PHP te gebruiken.
Kosten: Gratis.
Voordelen:
Perfect geschikt voor signing en tokenisatie.
Geen extra afhankelijkheden.
Nadelen:
Sleutels zelf beheren.
Beide bieden RSA key management via API.
Kosten: €1 per 10.000 encrypties + sleutelbeheer.
Voordelen:
Managed sleutelbeheer.
Nadelen:
API latency.
Vendor lock in.
OpenSSL in PHP is sneller, goedkoper en zonder lock in.
Geen voordeel in SaaS.
ECC is ondersteund in PHP via OpenSSL.
Kosten: Gratis.
Voordelen:
Veiliger dan RSA met kleinere sleutels.
Geschikt voor signing.
Nadelen:
Zelf sleutelbeheer regelen.
Bieden ECC key management via KMS API.
Kosten: €1 per 10.000 calls + key fees.
Voordelen:
Gemakkelijk beheer.
Nadelen:
Externe calls.
Kosten lopen snel op.
OpenSSL via PHP is sneller en veiliger voor ons scenario. SaaS KMS voegt kosten en afhankelijkheid toe.
De markt biedt veel oplossingen, maar:
Vrijwel allemaal SaaS-oplossingen met hoge kosten en vendor lock-in.
Vaak generiek, zonder begrip van ons softwareplatform of PHPecosystemen.
Integratie in onze bestaande PHP-stack is lastig of onmogelijk.
Licenties en API kosten lopen bij hoge volumes flink op.
Daarom is zelf ontwikkelen PHP de meest logische, veilige en voor de organisatie leerzame keuze:
Geen latency.
Lage vaste kosten.
Volledige controle over data, sleutels en compliance.
Geen vendor lock-in.
Exact afgestemd op onze eigen software en datastromen.
In deze risicoanalyse bekijken we de beveiligingsrisico’s rond onze fintechwebapplicatie die in native PHP is gebouwd en gevoelige persoonsgegevens en vermogensgegevens van fondsdeelnemers verwerkt. Per beveiligingstechniek of methode bespreken we welke typen risico’s (technisch, economisch en maatschappelijk) ermee gepaard gaan en hoe groot wij de dreiging achten van datalekken of cyberaanvallen. Ons team is technisch onderlegd in PHP, dus waar nodig duiken we de diepte in.
Technisch risico:
Data masking houdt in dat gevoelige data onherkenbaar wordt gemaakt, bijvoorbeeld door namen, BSN-nummers of saldi te vervangen of gedeeltelijk te verbergen. In onze PHP applicatie gebruiken we dit om ervoor te zorgen dat ontwikkelaars of externe partijen in test- of rapportage omgevingen niet de echte persoonsgegevens zien, maar gemaskeerde waarden. Hoewel dit eenvoudiger lijkt dan zware cryptografie, schuilen er ook hier risico’s. Gemaskeerde data is vaak pseudoniem in plaats van volledig anoniem. Dat betekent dat er nog steeds een mogelijkheid is om individuen te herleiden als je de gemaskeerde dataset koppelt aan andere informatiebronnen.
Gemaskeerde (gepseudonimiseerde) gegevens kunnen zo een vals gevoel van veiligheid geven, zelfs als direct identificerende velden zijn vervangen, kan koppeling met andere datasets alsnog personen blootleggen. Ons team moet beseffen dat een zelfgebouwde maskeringsfunctie misschien niet alle indirecte herkenningspunten verwijdert. Een praktisch risico is bijvoorbeeld dat we een deel van een veld zichtbaar laten (zeg de laatste 4 cijfers van een rekeningnummer) en dat die fragmenten, gecombineerd met andere kennis, iemands identiteit prijsgeven. Ook kunnen er bugs optreden waardoor data niet altijd gemaskeerd wordt (bijvoorbeeld een bepaalde export die per ongeluk onbewerkt blijft). De waarschijnlijkheid van dit soort fouten is reëel, het is een plain php bestaand software systeem en dat vergroot de kans op edge cases die over het hoofd worden gezien.
Dreiging van datalekken:
Een datalek bij data masking kan betekenen dat derden alsnog bij onderliggende persoonsgegevens kunnen komen, ondanks dat wij dachten ze af te schermen. Stel dat een kwaadwillende insider of hacker onze gemaskeerde dataset in handen krijgt. Op het eerste gezicht lijkt die dataset waardeloos, maar door slim speurwerk kan hij patronen herkennen of de data correleren met openbare bronnen.
Bijvoorbeeld, als wij geboortejaren maskeren maar woonplaatsen niet, zou iemand via externe demografische data alsnog specifieke personen kunnen identificeren. De impact van zo’n lek is hoog: we hebben dan persoonlijke of financiële informatie prijsgegeven terwijl we dachten veilig te zijn. Daarnaast overtreden we mogelijk de privacywetgeving; onder de AVG geldt pseudonieme data nog steeds als persoonsgegevens, dus een lek daarvan is een ernstig incident net als bij onbewerkte data. De kans op dit scenario is aanzienlijk wanneer we vertrouwen op eenvoudige maskering als voornaamste bescherming. Het is vaker voorgekomen dat “geanonimiseerde” datasets toch herleidbaar blijken, wat aangeeft dat pure masking een zwakkere vorm van beveiliging is vergeleken met echte encryptie of strikte toegangscontrole.
Economisch risico:
Op economisch vlak kan een mislukte data masking dure consequenties hebben. Ten eerste kunnen toezichthouders boetes opleggen als gemaskeerde data toch herleidbaar blijkt en uitlekt. De Autoriteit Persoonsgegevens is niet mild wanneer een bedrijf gevoelige informatie laat lekken, ook al was die zogenaamd geanonimiseerd. We moeten rekening houden met mogelijke AVG-boetes of juridische claims van gedupeerde klanten. Verder zijn er de kosten van incidentrespons: forensisch onderzoek, melding aan gedupeerden, public relations en reputatieherstel, al deze stappen kosten geld en mankracht.
Ook intern kan gebrekkige maskering financiële schade veroorzaken. Denk aan verkeerde beslissingen op basis van gemaskeerde data. Als we data masken voor analytische doeleinden maar dat proces fouten bevat, kunnen onze analyses onjuiste resultaten opleveren. Dat kan leiden tot slechte beslissingen, wat zich indirect vertaalt in verlies of gemiste winst. Ten slotte kan het vertrouwen van participanten een deuk oplopen als bekend wordt dat ons databeveiligingsbeleid gaten vertoont. Dat kan de bedrijfswaarde aantasten en toekomstige investeringen of samenwerkingen bemoeilijken.
Maatschappelijk risico:
Bij data masking draait het maatschappelijke aspect om vertrouwen en transparantie. Geintresseerden en fondsdeelnemers verwachten dat hun gegevens veilig zijn. Als wij communiceren dat we data “anonymiseren”, rekent men erop dat dit werkelijk betekent dat hun privacy beschermd is. Als later blijkt dat dit niet waterdicht was en data toch te herleiden was, voelen mensen zich misleid en onveilig. Onze geloofwaardigheid als fintechaanbieder krijgt dan een flinke deuk.
Technisch risico:
Secure Multi-Party Computation (MPC) is een cryptografische methode waarbij meerdere partijen samen een berekening uitvoeren zonder elkaar hun inputgegevens prijs te geven. In een fintechcontext zou ons PHPteam MPC bijvoorbeeld kunnen inzetten om privacygevoelige financiële berekeningen uit te voeren in samenwerking met andere instanties (denk aan gezamenlijke fraude-analyse) zonder dat ruwe data gedeeld wordt. Het concept biedt sterke bescherming van vertrouwelijkheid, maar technisch gezien brengt de implementatie in native PHP flinke uitdagingen mee. Er is geen kant en klare PHP library voor geavanceerde MPC protocollen, dus het team zou moeten leunen op complexe externe cryptografische code of zelf iets ontwikkelen, beide opties verhogen de kans op programmeerfouten of subtiele kwetsbaarheden.
Bovendien zijn er geen externe partijen waarmee data gedeeld wordt, data wordt alleen door ons ingelezen vanuit externe partijen.
MPC vereist veel communicatie en coördinatie tussen de partijen: er is een aanzienlijke performance overhead doordat partijen continu tussentijdse resultaten en versleutelde gegevens moeten uitwisselen Dit betekent dat onze applicatie trager kan worden en mogelijk schaalbaarheidsproblemen krijgt.
Zolang wij geen externe partij hebben waarmee wij actief data delen, is MPC voor ons nog niet interessant.
Wel gaan we het theoritsch uitwerken en de kosten analyseren zodat we het op de plak klaar hebben liggen zodra deze wens zich wel voordoet.
Dreiging en impact van datalekken:
Hoewel MPC ontworpen is om datalekken te voorkomen door data nooit centraal bloot te stellen, zijn er scenario’s denkbaar waarbij toch gevoelige informatie op straat komt. Een technisch scenario is dat één van de partijen in het MPC-protocol kwaadaardig of gecompromitteerd is. Als de beveiliging ervan uitgaat dat een meerderheid van partijen eerlijk is, kan een aanvaller die controle krijgt over voldoende partijen of hun cryptografische shares de vertrouwelijke inputdata reconstrueren. In ons geval zou dat betekenen dat gevoelige persoonsgegevens of saldo informatie alsnog uitlekt ondanks het gebruik van MPC. De impact daarvan is hoog, want men waant zich veilig door MPC en deelt mogelijk extra gevoelige data. De waarschijnlijkheid hangt af van hoe streng het MPC protocol is: bij een robuust protocol met een ‘malicious adversary’ beveiligingsmodel is de kans kleiner, maar gezien de complexiteit is het niet ondenkbaar dat implementatiefouten of verkeerde aannames toch een opening bieden.
Economisch risico:
De economische gevolgen van problemen met MPC kunnen fors zijn. Allereerst is er de ontwikkel en operationele kosten: MPC technologie implementeren vergt van het team veel tijd en gespecialiseerde kennis, wat zich vertaalt in hogere ontwikkelkosten. Als de performance tegenvalt, moeten we mogelijk investeren in zwaardere infrastructuur of accepteren dat sommige analyses niet realtime kunnen plaatsvinden, wat de dienstverlening flink zal verslechteren. Dat raakt de klanttevredenheid en potentieel de omzet als processen merkbaar vertragen.
Nog erger is een scenario waarin MPC faalt in zijn opzet en een datalek plaatsvindt. Financiële toezichthouders zullen weinig genade hebben als uitgerekend een geavanceerde beveiligingstechnologie faalt, omdat dit kan wijzen op nalatigheid of overschatting van eigen kunnen. De reputatieschade die volgt (een maatschappelijk effect) leidt bovendien vaak tot klantenverlies en verminderd marktaandeel, wat eveneens direct economische impact heeft.
Maatschappelijk risico:
Op maatschappelijk vlak speelt vertrouwen een grote rol. Fintechdiensten draaien op het vertrouwen van deelnemers (welke een volledige screening ondergaan inclusief herkomst en totaliteit aan vermogen) dat hun data veilig is en processen eerlijk verlopen. MPC belooft sterk verbeterde privacy, dus als er toch iets misgaat, bijvoorbeeld een lek of een onopgemerkte manipulatie van data, is de schok extra groot. De gemiddelde gebruiker of fondsdeelnemer begrijpt de technische details van MPC wellicht niet, maar zal horen dat “zelfs een geavanceerde cryptotechniek de gegevens niet heeft kunnen beschermen”. Dat ondermijnt het vertrouwen in ons bedrijf en misschien ook in innovatieve databeveiliging in het algemeen.
Ook toezichthouders en partnerorganisaties (zoals subfondsbeheerders waarmee we in een MPC-proces samenwerken) zullen bij een incident terughoudender worden om zulke geavanceerde samenwerkingen voort te zetten. Bovendien kan er publieke onrust ontstaan als gevoelige financiële gegevens uitlekken; deelnemers kunnen zich collectief zorgen gaan maken over identiteitsdiefstal of misbruik van hun informatie. Kortom, een misstap met MPC kan op brede schaal de acceptatie van privacygerichte technologieën schaden en zet onze organisatie neer als een partij die onverantwoordelijk met gevoelige data omgaat.
Technisch risico:
Data Loss Prevention is een verzamelnaam voor technologieën en processen die moeten voorkomen dat gevoelige informatie de organisatie ongewenst verlaat. Vaak betreft het software die uitgaande stromen controleert, denk aan e-mails, uploads, USB-opslag en alarm slaat of blokkeert als er bijvoorbeeld BSN-nummers, financiële gegevens of andere Persoonlijk identificeerbare informatie (PII) naar buiten dreigen te gaan. In onze fintechcontext zou een DLP oplossing bijvoorbeeld kunnen meekijken met welke data onze PHP app verstuurt (via e-mailfunctionaliteit, API’s of downloads) en ervoor zorgen dat klantgegevens niet zomaar bij onbevoegden belanden. Ook zouden we exporteren van data streng kunnen afschermen en voorzien van een audit log. Het technische risico is dat de kans dat DLP niet alles onderschept wat het zou moeten.
Anderzijds kan DLP ook te streng zijn en gewenste handelingen blokkeren. Zo kan ons developmentteam tijdens het bouwen van functionaliteit merken dat bepaalde mail rapportage bestanden of routine-uitgaande mails telkens worden tegengehouden omdat ze “gevoelige strings” bevatten, terwijl het in context geen echt lek is. Dit kan de ontwikkeling en operationele processen vertragen en frustratie veroorzaken, wat indirect weer veiligheidsrisico’s kan opleveren (bijvoorbeeld dat ons team geneigd is de DLP uit te schakelen om toch te kunnen werken).
Dreiging en lekscenario’s:
Ondanks DLP blijft het risico op datalekken aanwezig. Bijvoorbeeld, een medewerker met toegang tot data kan deze alsnog moedwillig of per ongeluk gevoelige gegevens naar buiten brengen.
DLP kan bijvoorbeeld een poging onderscheppen wanneer iemand een klantenlijst naar een probeert te exporteren, maar een vastberaden insider vindt mogelijk manieren om het systeem te omzeilen (bijv. door informatie rechtstreeks uit de database te halen, screenshots te maken, of gebruik van ongecontroleerde kanalen). Ook externe aanvallers vormen een dreiging: als een hacker ons PHP systeem compromitteert, zal hij proberen data te exporteren op manieren die DLP niet herkent, bijvoorbeeld door databasevelden te exporteren.
De impact van een succesvol datalek is enorm. We hebben het over er gevoelige klantgegevens inclusief vertrouwelijke financiële data die op straat komen. Zelfs als het volledig per ongeluk gebeurt (dus zonder kwade opzet), zijn de gevolgen van een datalek openbaar enorm, met hoge boetes en zelfs strafrechtelijke sancties als resultaat. Onze deelnemers en klanten verliezen het vertrouwen, en de media aandacht rond een dergelijk lek kan de reputatie van onze fintech software onderneming onherstelbaar beschadigen.
De waarschijnlijkheid van een datalek is moeilijk precies in te schatten, maar we moeten rekening houden met het menselijke element: waar mensen met data omgaan, worden fouten gemaakt. En cybercriminelen zijn continu op zoek naar zwakke plekken; als onze DLP configuratie ergens een gat laat (door misconfiguratie of beperkte reikwijdte), is de kans aanwezig dat het uitgebuit wordt.
Economisch risico:
Data Loss Prevention raakt ook direct de bedrijfsvoering en financiën. Ten eerste kost de implementatie en het beheer van DLP-tools geld en mankracht: licentiekosten, infrastructuur en dedicated analisten om alerts te monitoren. Dit is op zich een geplande uitgave, maar wel een significante.
Als DLP echter faalt en een lek optreedt, volgen de onvoorziene kosten. Net als bij andere beveiligingsincidenten kunnen die bestaan uit boetes (Autoriteit Persoonsgegevens kan stevige geldstraffen uitdelen), juridische kosten voor eventuele rechtszaken en de kosten om het incident te onderzoeken en op te ruimen. Daarbij komen de indirecte economische gevolgen: reputatieschade kan leiden tot klantenverlies, wat in de vorm van gederfde inkomsten pijn doet.
Ook het interne effect, bijvoorbeeld productiviteitsverlies door al te strenge DLP-regels, heeft economisch impact. Als werknemers voortdurend omslachtig moeten werken om de beveiliging niet in de weg te zitten, gaat kostbare tijd verloren die anders productief besteed kon worden. In het ergste geval kunnen frustraties over DLP ertoe leiden dat talentvolle medewerkers afhaken of dat afdelingen noodoplossingen gaan gebruiken buiten het zicht van DLP, wat later weer tot dure incidenten kan leiden.
Maatschappelijk risico:
Maatschappelijk gezien draait het om verantwoording en vertrouwen. Een bedrijf dat aan financiële dienstverlening doet, wordt geacht goed op zijn data te passen. Als er ondanks DLP een datalek plaatsvindt, zullen publiek en toezichthouders concluderen dat we onze zaakjes niet op orde hadden. Zeker omdat DLP in feite een vangnet is, als zelfs het vangnet faalt, lijkt het alsof we roekeloos zijn geweest. Dit kan leiden tot strengere eisen van toezichthouders of verlies van certificeringen.
Klanten van het fonds zullen zich afvragen of hun gegevens ooit veilig kunnen zijn in onze handen en kunnen weglopen.
Tegelijk moeten we intern oppassen dat DLP maatregelen niet botsen met privacyverwachtingen van werknemers: wanneer al het verkeer gemonitord wordt, kan dat tot ethische vragen leiden en de bedrijfscultuur negatief beïnvloeden.
Uiteindelijk beïnvloedt een lek of te streng toezicht op data niet alleen onze eigen reputatie, maar voedt het de maatschappelijke angst dat persoonlijke financiële informatie nergens meer veilig is. Dat schaadt het vertrouwen in digitale financiën als geheel.
Technisch risico:
API’s vormen de ruggengraat van onze fintechapplicaties. Onze PHP app gebruikt API-endpoints, bijvoorbeeld voor onze webportals en integraties met interne microservices. Gezien het plain PHP applicaties betreffen, hebben onze teams deze API’s zelf ontwikkeld en dienen ze deze ook zelf te beveiligen. Technisch brengt dat risico’s mee: we moeten eigenhandig zorgen voor authenticatie, autorisatie, input validatie en beveiliging tegen bekende aanvalsvectoren. Een klein foutje, bijvoorbeeld vergeten om te controleren of een gebruiker wel bevoegd is voor een bepaalde dataset, kan ertoe leiden dat gevoelige klantinformatie via de API voor onbevoegden toegankelijk is.
Dreiging en kwetsbaarheidsscénario’s:
API’s zijn een populair doelwit voor cyberaanvallers, omdat ze direct toegang geven tot backend gegevens en functionaliteit.
Als wij een fout maken in de API-beveiliging, kan dat snel ontdekt en misbruikt worden, vaak zelfs geautomatiseerd.
Een voorbeeldscenario is Broken Object Level Authorization (BOLA): de API verwacht bijvoorbeeld een accountID in de URL en we halen op basis daarvan gegevens op, maar als we niet strikt controleren of die ID bij de ingelogde gebruiker hoort, kan een kwaadwillende simpelweg een ID van iemand anders invullen en zo diens data inzien. Dergelijke autorisatiefouten behoren tot de top API kwetsbaarheden en hebben vaak ernstige gevolgen.
Ook broken authentication is een risico: als onze sessietokens of API keys niet goed worden behandeld (bijv. gemakkelijk te raden), kunnen aanvallers zich voordoen als legitieme gebruikers. Daarnaast blijven klassieke aanvallen als SQL-injectie en cross-site scripting relevant als input niet streng gevalideerd wordt. Via een kwetsbare API kan een aanvaller mogelijk direct onze database uitlezen of zelfs transacties manipuleren.
De impact hiervan is zeer groot: persoonlijke gegevens (namen, adressen, portefeuillesaldi) en mogelijk zelfs financiële transacties liggen op straat. Zo’n inbreuk betekent niet alleen een verlies van vertrouwelijkheid, maar ook een overtreding van privacy- en financiëleregelgeving, met boetes en juridische gevolgen van dien. Bovendien kan de aanvaller de buitgemaakte gegevens misbruiken voor identiteitsdiefstal of financieel fraude, en ons platform inzetten om verdere aanvallen uit te voeren. De waarschijnlijkheid dat iemand onze API’s aanvalt is hoog, er draaien constant bots en scanners op internet die zwakke API endpoints zoeken. Als we beveiligingsfouten hebben, is de kans reëel dat ze vroeg of laat worden uitgebuit.
Economisch risico:
Een incident via de API kan direct in de papieren lopen. Ten eerste bestaat de mogelijkheid van financiële schade voor onze klanten (bijvoorbeeld pulieke blootstelling van hun totaalvermogen).
In zo’n geval kunnen we aansprakelijk gesteld worden voor die blootstelling. Daarnaast zijn er de kosten voor het bedrijf zelf: we moeten incident response doen, forensic onderzoek, eventueel vervangende diensten verlenen en klanten compenseren.
Regelgevers kunnen forse boetes uitdelen vanwege nalatigheid bij het beschermen van data of assets. Intussen kunnen door publiciteit nieuwe klanten wegblijven en bestaande klanten vertrekken, wat neerkomt op gederfde toekomstige inkomsten.
Ook moeten we na een incident waarschijnlijk extra investeren in beveiliging (nieuwe tools, externe audits, meer ontwikkeltijd voor fixes), wat niet begroot was.
Kortom, een succesvolle API-aanval is financieel dubbel schadelijk: directe verliezen en strafmaatregelen, plus langere termijn omzetdaling en extra kosten.
Maatschappelijk risico:
Op maatschappelijk vlak vormt een API hack een grote deuk in het vertrouwen. Klanten vertrouwen ons hun geld en gegevens toe; als een simpele API fout dat allemaal prijsgeeft, zullen velen zich afvragen of fintechplatforms wel veilig genoeg zijn. Het incident kan breed uitgemeten worden in de pers, wat onze reputatie ernstig schaadt.
Ons bedrijf kan bekend komen te staan als voorbeeld van slechte beveiliging, wat voor de hele branche nadelig is.
Mensen worden terughoudender om financiële innovaties te vertrouwen. Toezichthouders grijpen bij zulke incidenten vaak in met strengere regels of extra toezicht, wat de operationele vrijheid van ons en andere fintechs beperkt.
Bovendien kan een grote API datakraak leiden tot reële schade bij individuen (identiteitsfraude, doelwit van phishing doordat hun gegevens gelekt zijn), wat onze maatschappelijke verantwoordelijkheid als financiële instelling in twijfel trekt. Kortom, falende API beveiliging zet niet alleen onze eigen organisatie, maar ook onze klanten en het bredere vertrouwen in digitaal financieren op het spel.
Technisch risico:
AES (Advanced Encryption Standard) is een krachtige symmetrische versleutelingsmethode die we in onze fintechapplicatie kunnen gaan gebruiken om gevoelige data te beveiligen (bijvoorbeeld encryptie van klantgegevens in de database of versleutelde opslag van bestanden en backups). Hoewel AES zelf cryptografisch zeer sterk is, schuilt het gevaar in hoe we het toepassen. In native PHP moeten we zorgvuldig de implementatie doen via bijvoorbeeld OpenSSL-functies. Een bekende valkuil is het gebruik van een onveilig werkingsmodus, zoals Electronic Codebook (ECB). AES in ECB-modus versleutelt elk blok data los van de rest, hierdoor krijgen identieke patronen in de plaintext identieke patronen in de ciphertext, wat informatie kan verraden. Anders gezegd: als een hacker een versleutelde dataset onderschept die met ECB is versleuteld, kan hij misschien nog steeds patronen of herhalingen herkennen.
Daarnaast is sleutelbeheer een technisch risico: als wij de AES-sleutels hardcoded in de PHP-code zetten of onbeveiligd op de server opslaan, dan is de sterkte van AES irrelevant, een aanvaller die inbreekt in de server kan de sleutel eenvoudig meenemen.
Dreiging van datalekken:
In het ergste geval kan een aanvaller de encryptie ongedaan maken en de gevoelige data lezen of manipuleren. Dit kan gebeuren als hij de sleutel te pakken krijgt of als we een zwakke configuratie gekozen hebben. Bijvoorbeeld, als onze applicatie per ongeluk een vaste, voorspelbare encryptiesleutel gebruikt (of een wachtwoord als sleutel), zou een aanvaller door brute force of herleiding de sleutel kunnen achterhalen. Heeft een aanvaller de AES-sleutel eenmaal in handen, dan kan hij alle daarmee versleutelde gegevens ontsleutelen, in ons geval mogelijk volledige klantenbestanden, transactiehistorie, et cetera.
Ook zonder de sleutel zijn er dreigingen: zoals genoemd kan een verkeerde modus als ECB bepaalde patronen prijsgeven aan iemand die de versleutelde data ziet. Evenzo leidt het ontbreken van integriteitscontrole ertoe dat een aanvaller versleutelde gegevens onopgemerkt kan aanpassen. Denk aan het wijzigen van een versleuteld saldo of het manipuleren van versleutelde instellingen; de ontvanger merkt pas bij gebruik dat er iets mis is, of erger nog, de fout blijft onopgemerkt.
De impact van een dergelijk encryptielek is enorm: data die we dachten veilig te hebben opgeslagen, komt alsnog op straat te liggen of wordt subtiel vervalst. Hoewel AES zelf niet zomaar “gekraakt” kan worden, blijken in praktijk vaak de implementatiefouten de zwakke schakel.
De waarschijnlijkheid van misbruik is vooral gekoppeld aan die fouten: als we alles volgens best practice doen is de kans op een succesvolle aanval zeer klein, maar gezien we zonder frameworks werken en alles maatwerk is, moeten we rekening houden met een verhoogde kans op een vergissing die een oplettende aanvaller kan uitbuiten.
Economisch risico:
Als onze AES encryptie faalt door een fout, heeft dat vergelijkbare gevolgen als een regulier datalek. We verliezen immers de vertrouwelijkheid van persoons en vermogensgegevens. Economisch betekent dit dat we boetes riskeren onder privacywetgeving (AVG) omdat gevoelige data ongeoorloofd is onthuld. Fintechs behoren encryptie op orde te hebben; een gecompromitteerde database zonder effectieve encryptie kan leiden tot flinke sancties en juridische claims. Daarnaast moeten we bij een dergelijk incident onze klanten informeren en mogelijk compenseren, wat directe kosten met zich meebrengt. Er is ook de kostenpost van forensisch onderzoek en het dichten van het lek.
Verder kan een encryptieprobleem leiden tot operationele verstoringen: stel dat we ineens alle data opnieuw moeten versleutelen met een beter algoritme of sleutelrotatie moeten uitvoeren, dat vergt tijd, rekenkracht en kan downtime veroorzaken, met indirecte financiële schade (bijvoorbeeld gemiste transacties) als gevolg. Tot slot raakt het incident het vertrouwen van partners; zij investeren in een fintech met de verwachting dat basisbeveiliging zoals encryptie solide is, en een falen hierin kan de bedrijfswaarde en toekomstige investeringen negatief beïnvloeden.
Maatschappelijk risico:
Vanuit het oogpunt van klanten en samenleving is encryptie zo’n beetje de standaardverwachting: men gaat ervan uit dat financiële instellingen hun data versleutelen. Als blijkt dat onze AES-encryptie ineffectief was en er data uitlekt, zullen klanten dit zien als een groot verzuim. Het vertrouwen in onze organisatie krijgt een klap; mensen zullen zich afvragen of hun gegevens ooit echt veilig geweest zijn. Ook op brancheniveau schaadt het het imago van fintechs, een incident waarbij versleutelde data toch uitlekt, voedt het beeld dat “die nieuwe financiële spelers hun beveiliging niet op orde hebben”. Regulators kunnen strenger optreden: mogelijk worden we tijdelijk beperkt in het verwerken van nieuwe klanten of moeten we onder verscherpt toezicht onze encryptie-methoden verbeteren. Bovendien heeft een encryptielek direct invloed op individuen: gelekte persoonlijke en financiële gegevens kunnen misbruikt worden door criminelen, met alle gevolgen van dien voor de betrokken personen. Mensen rekenen erop dat encryptie hen beschermt, en als dat schild faalt, verliest men vertrouwen in digitale financiële diensten.
Technisch risico:
RSA is een asymmetrisch cryptosysteem dat we kunnen gebruiken voor bijvoorbeeld het uitwisselen van geheimen (zoals het versturen van een AES-sleutel). Anders dan AES berust RSA op een publiek-privaat sleutelpaar en wiskundige moeilijkheid (factoring van grote getallen). Technische risico’s bij RSA liggen met name in sleutellengte, generatie en implementatie. Als we te zwakke sleutels gebruiken (bijvoorbeeld 1024-bit in plaats van minimaal 2048-bit), wordt het voor aanvallers een stuk makkelijker om de sleutel te kraken.
Maar zelfs bij nominaal sterk lijkende sleutels kan er iets misgaan: nieuw onderzoek ( toont aan dat ongeveer 1 op de 172 RSA-certificaten wereldwijd kwetsbaar is door foutieve sleutelgeneratie, wat neerkomt op potentieel miljoenen sleutels die te breken zijn (brond: itpro.com). Ook in onze context, als wij zelf RSA-sleutels genereren zonder goede random number generator, zouden we per ongeluk sleutels kunnen creëren die factoren delen met andere sleutels, waardoor ze kraakbaar worden. Ons PHP-team moet deze complexe details zelf afvangen, wat een uitdaging is.
Ten slotte is er nog de opkomende dreiging van kwantumcomputers: in theorie kunnen toekomstige kwantumalgoritmes grote RSA-sleutels breken, wat betekent dat op termijn RSA als methode onveilig kan worden.
Dreiging en impact:
Een compromis van RSA kan catastrofaal zijn, omdat het doorgaans een centrale rol speelt in de beveiliging. Stel dat onze private RSA sleutel in verkeerde handen valt (bijvoorbeeld door een serverinbraak of een lek in onze opslag ervan): een aanvaller kan dan alle informatie die met de corresponderende publieke sleutel versleuteld is ontcijferen. In de praktijk zou dat betekenen dat hij geheime sessiesleutels of gevoelige berichten kan ontsleutelen, en mogelijk zelfs digitale handtekeningen kan vervalsen. Als onze applicatie bijvoorbeeld RSA gebruikt om berichten te ondertekenen, kan een aanvaller met de gestolen sleutel valse berichtgevingen autoriseren of zich als een legitieme partij voordoen.
Zelfs zonder diefstal zijn er scenario’s waarbij RSA gekraakt wordt door berekeningen: lukt het iemand om onze publieke sleutel te krakgen (bijv. omdat we een zwakke sleutel gebruikten of omdat een geavanceerde aanval de wiskundige structuur misbruikt), dan is het net zo erg alsof de sleutel gestolen was.
De impact is enorm: alle vertrouwelijke communicatie die we dachten te beschermen met RSA is ineens inzichtelijk voor de aanvaller, en de integriteit van onze transacties of authenticatie kan ondermijnd worden. Klantgegevens, interne bedrijfsgeheimen, API verkeer, alles wat op RSA vertrouwde is dan kwetsbaar.
De waarschijnlijkheid van zo’n scenario hangt gelukkig af van hoe goed we de techniek toepassen. Een sterke, goed gegenereerde RSA-sleutel is vandaag de dag niet zo makkelijk te breken zonder gigantische rekenkracht. Echter, komen slordigheden voor en geautomatiseerde tools kunnen zwakke sleutels relatief snel identificeren. Daarnaast is er de langere termijn: het is geen kwestie of maar wanneer kwantumcomputers RSA zullen kunnen breken. Voor data die nu wordt onderschept en jarenlang bewaard, bestaat het risico dat het in de toekomst alsnog ontcijferd wordt zodra de technologie het toelaat.
Economisch risico:
Een doorbroken RSA-beveiliging in onze applicatie zou leiden tot scenario’s vergelijkbaar met een zwaar datalek of grootschalige fraude. Als een aanvaller RSA wist te compromitteren, kan hij financiële transacties inzien of vertrouwelijke klantinformatie stelen. Financieel kan dit direct leiden tot grote verliezen, wij zouden aansprakelijk kunnen zijn schade bij klanten. De boetes en claims zouden fors zijn, gezien het gaat om falen van fundamentele beveiliging.
Daarnaast komen de incidentkosten: systemen moeten mogelijk stilgelegd worden, sleutels vervangen, en een diepgaand onderzoek moet uitgevoerd worden naar de aard en scope van het incident. De ontwikkelaars zullen tijd moeten steken in het vervangen van RSA door veiligere alternatieven of het versterken van de implementatie, wat vertraging en extra kosten met zich meebrengt. Ondertussen verliest het bedrijf omzet doordat klanten tijdelijk afhaken of nieuwe klanten wegblijven vanwege imagoschade. Ook participanten kunnen nerveus raken.
Kortom, de financiële gevolgen bewegen zich op meerdere fronten: directe operationele verliezen, juridischekosten en langdurige reputatieschade met omzetverlies.
Maatschappelijk risico:
Publiek en klanten zullen een RSA gerelateerd incident zien als een teken dat onze beveiliging ernstig tekortschiet. RSA wordt vaak gezien als een van de pilaren van online security; als bij ons blijkt dat die pilaar instort (door zwakke sleutels of slechte implementatie), tast dat het vertrouwen in onze organisatie enorm aan. Klanten zullen zich afvragen of hun gegevens en hun geld wel veilig zijn geweest. Bovendien kan zo’n incident een bredere discussie aanwakkeren over cryptografie in de financiële sector.Ten slotte hebben de participanten waarvan data of financiële transacties gecompromitteerd zijn, te lijden onder de gevolgen van identiteitsdiefstal.
Gezien de risco's bljikt RSA voor een financieel fonds minder geschikt.
Technisch risico:
Elliptic Curve Cryptography (ECC) is een modernere vorm van asymmetrische cryptografie die kleinere sleutels gebruikt voor vergelijkbare sterkte als RSA. In een fintech-omgeving kan ECC bijvoorbeeld ingezet worden voor sleuteluitwisseling (ECDH voor het opzetten van TLS-verbindingen). Het voordeel is efficiëntere cryptografie, maar technisch brengt ECC zijn eigen uitdagingen mee. Een van de grootste risico’s zit in de implementatie: het algoritme zelf is robuust, maar een klein foutje kan de geheime sleutel verraden.
Zo is het essentieel om een volledig willekeurige, unieke handtekening te gebruiken; als twee handtekeningen per ongeluk dezelfde of gerelateerde “nonce” gebruiken, kan een aanvaller met wat wiskunde de private key achterhalen. In PHP zullen we waarschijnlijk vertrouwen op OpenSSL voor ECC functionaliteit, maar we moeten die ook juist aanroepen. Bijvoorbeeld, verkeerde parameters of het nalaten om de geldigheid van publieke punten te controleren kan leiden tot aanvallen. ECC vergt ook goede random number generation, voorspelbaarheid in onze random generator kan betekenen dat de gegenereerde sleutels te raden zijn.
Daarnaast gelden vergelijkbare zorgen als bij RSA: te korte sleutels of onbekende zelfverzonnen curves zijn vragen om problemen. Quantumcomputers vormen op termijn ook voor ECC een bedreiging, vergelijkbaar met RSA, al is onduidelijk wanneer dit praktisch relevant wordt.
Dreiging en impact:
Een compromis van een ECC-sleutel heeft vergelijkbare gevolgen als bij RSA: de aanvaller kan vertrouwelijke informatie ontsleutelen of valse handtekeningen zetten. Als door een lek in de implementatie onze private sleutel wordt blootgelegd, kan de aanvaller transacties vervalsen alsof hij onze identiteit heeft. Als ECC bij ons voor sleuteluitwisseling dient en iemand achterhaalt onze langdurige private sleutel, dan kan hij mogelijk de vertrouwelijkheid van sessies breken door achteraf de gedeelde geheimen te reconstrueren.
De impact is ook hier zeer ernstig: een aanvaller kan zich voordoen als een legitieme partij in het systeem, transacties autoriseren zonder toestemming van de echte gebruiker, of versleutelde klantgegevens ontcijferen. In wezen verliest ECC dan zijn hele nut als beschermingslaag, alles wat ervan afhankelijk was, ligt open voor misbruik.
De kans op zo’n ECC-fiasco is klein als we de best practices volgen en op beproefde libraries steunen, maar zeker niet nul. Er zijn reële voorbeelden geweest van fouten met nonces of slechte random generators die tot sleutelcompromitties leidden (bijvoorbeeld in cryptocurrency-wallets). Omdat ons team zonder framework werkt en zelf verantwoordelijk is voor de integratie van deze cryptografie, bestaat het risico dat zo’n fout onopgemerkt blijft tot een aanval plaatsvindt.
Economisch risico:
De economische schade door een ECC lek: We kunnen te maken krijgen met directe financiële verliezen als er de gegevens van onze participanten op straat komen te liggen. Daarbij komen mogelijke boetes van toezichthouders (AFM), zeker als uit onderzoek blijkt dat het probleem te wijten was aan een slordigheid in onze implementatie.
Net als bij andere datalekken moeten we rekenen op incidentafhandeling kosten: systemen opschonen, sleutels intrekken en vervangen, externe audits om vertrouwen terug te winnen. Mogelijk moeten we onze hele security structuur herzien (bijvoorbeeld overstappen op een andere curve of een groter beveiligingsmarge inbouwen), wat ontwikkelingstijd en investeringen vergt.
Nieuwe klanten zullen huiverig zijn om zich aan te melden na zo’n gebeurtenis en bestaande klanten kunnen vertrekken, uit angst dat hun vermogen niet veilig is. Dit omzetverlies, gecombineerd met de incidentele kosten en juridische claims, maakt een ECC-gerelateerd incident financieel zeer pijnlijk.
Maatschappelijk risico:
Een falende ECC-beveiliging in een fintech app wordt door het brede publiek gezien als “weer een hack”, men maakt geen onderscheid welke cryptomethode faalde, alleen dát er gevoelige financiële data en vertrouwen verloren gingen. Toch is de context relevant: als we trots geadverteerd hadden met “geavanceerde elliptische-curve-beveiliging” dan wordt de klap bij falen des te harder. Klanten verliezen het vertrouwen en voelen zich mogelijk proefkonijn van experimenten met complexe cryptografie. Elke openbaarmaking van zo’n incident schaadt niet alleen ons imago maar zet ook vraagtekens bij de modernere beveiligingstechnieken in de financiële wereld. De roep om terug te grijpen op “ouderwetse, geteste” methodes of strengere regulering kan klinken, wat innovatie vertraagt.
public static function mask($sString, $iCount = 3, $sMask = '*')
{
$iLength = strlen($sString);
if($iLength > ($iCount * 2))
{
$sString = substr($sString, 0, $iCount) . str_repeat($sMask, $iLength - ($iCount * 2)) . substr($sString, $iLength - $iCount, $iCount);
}
return $sString;
}
public static function maskEmail($sEmail)
{
$aEmail = explode('@', $sEmail);
$iNameLength = strlen($aEmail[0]);
$iDomainLength = strlen($aEmail[1]);
if($iNameLength > 7)
{
$sEmail = static::mask($aEmail[0], 3);
}
elseif($iNameLength > 5)
{
$sEmail = static::mask($aEmail[0], 2);
}
else
{
$sEmail = static::mask($aEmail[0], 1);
}
$sEmail .= '@';
if($iDomainLength > 7)
{
$sEmail .= static::mask($aEmail[1], 3);
}
elseif($iDomainLength > 5)
{
$sEmail .= static::mask($aEmail[1], 2);
}
else
{
$sEmail .= static::mask($aEmail[1], 1);
}
return $sEmail;
}
public static function maskPhone($sPhone)
{
return static::mask($sPhone, 3);
}
public static function getToken($aBody, $sSecret, $iExpire = 3600)
{
$aHeader = [
'alg' => 'sha512',
'exp' => (($iExpire < 1000000) ? (time() + $iExpire) : $iExpire),
'typ' => 'JWT',
];
$sJWT = base64_encode(json_encode($aHeader, JSON_UNESCAPED_UNICODE));
$sJWT .= '.' . base64_encode(json_encode($aBody, JSON_UNESCAPED_UNICODE));
$sJWT .= '.' . base64_encode(clsString::toHash($sJWT, 'sha512', $sSecret));
return $sJWT;
}
public static function validateToken($sToken, $sSecret)
{
if(is_array($sToken)) // Treat as GET/POST data
{
$sToken = clsBrowser::getToken() ?: clsArray::getText($sToken, 'token') ?: '';
}
elseif(!is_string($sToken)) // Analyse post data
{
$sToken = clsBrowser::getToken() ?: clsPost::getText('token') ?: '';
}
if($aToken = explode('.', $sToken))
{
if(sizeof($aToken) == 3)
{
$aHeader = json_decode(base64_decode($aToken[0]), true, 3);
$aBody = json_decode(base64_decode($aToken[1]), true, 3);
$sSignature = base64_decode($aToken[2]);
$sSignatureCompare = clsString::toHash($aToken[0] . '.' . $aToken[1], 'sha512', $sSecret);
if(empty($aHeader['typ']) || ($aHeader['typ'] != 'JWT'))
{
return false;
}
elseif(empty($aHeader['alg']) || ($aHeader['alg'] != 'sha512'))
{
return false;
}
elseif(empty($aHeader['exp']) || ($aHeader['exp'] < time()))
{
return false;
}
elseif(strcasecmp($sSignature, $sSignatureCompare))
{
return false;
}
return $aBody ?: [];
}
return false;
}
return null;
}
{
"columns": [
{
"name": "password",
"protection_function": "clsProtection::maskAll"
},
{
"name": "email",
"protection_function": "clsProtection::maskEmail"
},
{
"name": "phone",
"protection_function": "clsProtection::maskPhone"
}
]
}<?php
/*
Connect to the API using the credentials of an API account
*/
$sApiUrl = ELO_API_URL;
$sApiUser = ELO_API_USER;
$sApiPass = ELO_API_PASS;
$sApiToken = null;
// Fetch token
$aRequestUrl = $sApiUrl . '/api/login';
$aRequestData = ['email' => $sApiUser, 'password' => $sApiPass];
if($aResponse = clsJson::post($aRequestUrl, $aRequestData))
{
if($aResponse['status']['error'])
{
echo "\r\n<br><br>DEBUG | FILE: " . basename(__FILE__) . ", LINE: " . __LINE__ . "<br>\r\n";
echo $aResponse['status']['description'];
exit;
}
$sApiToken = $aResponse['data']['token'];
echo '<b>Recieved token</b>: ' . BRLF . clsString::escapeHtml($aResponse['data']['token']);
}
// Fetch available resources
$aRequestUrl = $sApiUrl . '/api/access';
$aRequestData = ['token' => $sApiToken];
if($aResponse = clsJson::post($aRequestUrl, $aRequestData))
{
if($aResponse['status']['error'])
{
echo "\r\n<br><br>DEBUG | FILE: " . basename(__FILE__) . ", LINE: " . __LINE__ . "<br>\r\n";
echo $aResponse['status']['description'];
exit;
}
echo BRLF . BRLF . '<b>You have access to tables</b>: ';
foreach($aResponse['data'] as $aTableData)
{
echo BRLF . clsString::escapeHtml($aTableData['table']);
}
}
// Fetch resources
if($sApiToken)
{
$aRequestUrl = $sApiUrl . '/api/tasks'; // Resourcename = Tablename (without prefix)
$aRequestData = ['limit' => 3, 'columns' => ['record_id', 'title', 'description'], 'sort' => "record_id:DESC", 'token' => $sApiToken];
if($aResponse = clsJson::post($aRequestUrl, $aRequestData))
{
if($aResponse['status']['error'])
{
echo BRLF . BRLF . '<b>Recieved error for resource TASKS</b>: ';
echo BRLF . $aResponse['status']['description'];
exit;
}
echo BRLF . BRLF . '<b>Recieved data for resource TASKS</b>: ';
echo clsArray::toTable($aResponse['data']);
}
}
// Fetch resources
if($sApiToken)
{
$aRequestUrl = $sApiUrl . '/api/users'; // Resourcename = Tablename (without prefix)
$aRequestData = ['limit' => 3, 'columns' => ['record_id', 'name', 'email', 'password', 'phone', 'role'], 'sort' => "name:ASC", 'token' => $sApiToken];
if($aResponse = clsJson::post($aRequestUrl, $aRequestData))
{
if($aResponse['status']['error'])
{
echo BRLF . BRLF . '<b>Recieved error for resource USERS</b>: ';
echo BRLF . $aResponse['status']['description'];
exit;
}
echo BRLF . BRLF . '<b>Recieved data for resource USERS</b>: ';
echo clsArray::toTable($aResponse['data']);
}
}
// Fetch resources
if($sApiToken)
{
$aRequestUrl = $sApiUrl . '/api/employees'; // Resourcename = Tablename (without prefix)
$aRequestData = ['limit' => 3, 'columns' => ['record_id', 'title', 'description'], 'sort' => "record_id:DESC", 'token' => $sApiToken];
if($aResponse = clsJson::post($aRequestUrl, $aRequestData))
{
if($aResponse['status']['error'])
{
echo BRLF . BRLF . '<b>Recieved error for resource EMPLOYEES</b>: ';
echo BRLF . $aResponse['status']['description'];
exit;
}
echo BRLF . BRLF . '<b>Recieved data for resource EMPLOYEES</b>: ';
echo clsArray::toTable($aResponse['data']);
}
}
=== TASK OUTPUT ===
[
{
"description": "Doel/Resultaat: Na deze werkstap hebben we de doelstellingen van deze studie zijn bepaald, om na dit onderzoek te kunnen concluderen of er een Go of No-Go op een vervolg ontwikkeling is?\r\rDefinieer de scope van de studie, inclusief de systemen, processen en data die geëvalueerd zullen worden. * Breng de specifieke eisen en behoeften van GMU BV in kaart op het gebied van gegevensbeveiliging en cybersecurity. * Bepaal welke wettelijke en compliance-eisen van toepassing zijn.\r\rOrganisatie: uitvoering door GMU BV in Meppel en Amsterdam",
"record_id": "1",
"title": "1-HBH - Haalbaarheidsstudie - Plan van aanpak"
},
{
"description": "Doel/Resultaat: Na deze werkstap weten we of er kant-en-klare oplossingen c.q. componenten ingezet kunnen worden omdat die beschikbaar zijn in de markt en goedkoper zijn dan zelf ontwikkelen, dus keuzes maken welke onderdelen we zelf ontwikkeling en welke inkoop zijn?\r\r Onderzoek naar bestaande oplossingen (concurrentie), technologieën en tools op het gebied van gegevensbeveiliging en cybersecurity. * Evalueer de prestaties en kosten van deze oplossingen.\r\rOrganisatie: uitvoering door GMU BV in Meppel en Amsterdam",
"record_id": "2",
"title": "2-HBH - Haalbaarheidsstudie - Marktonderzoek"
},
{
"description": "Doel/Resultaat: Na deze werkstap hebben we inzicht in de risico’s met gradaties van impact, dus welke risico’s kunnen we met routinematige werkzaamheden mitigeren en welke risico’s moeten we isoleren en gericht aanvallen met een technisch nieuwe ontwikkeling?\r\r*Identificeer en beoordeel potentiële risico's en bedreigingen voor de organisatie, dus technisch, economisch en maatschappelijk. * Voer een risicobeoordeling uit om de waarschijnlijkheid en impact van verschillende soorten datalekkages en cyberaanvallen te bepalen.\r\rOrganisatie: uitvoering door GMU BV in Meppel en Amsterdam",
"record_id": "3",
"title": "3-HBH - Haalbaarheidsstudie - Risicoanalyse"
}
]
=== USER OUTPUT ===
[
{
"email": "a*i@gmu****ine",
"password": "********************************************************************************************************************************",
"phone": null,
"record_id": "3",
"role": "@"
},
{
"email": "me.*****nga@gma***com",
"password": "********************************************************************************************************************************",
"phone": "316*****343",
"record_id": "1",
"role": "S"
},
{
"email": "w.z****nge@gmu****ine",
"password": "********************************************************************************************************************************",
"phone": null,
"record_id": "2",
"role": "U"
}
]
{
public static function encrypt(
string $data,
string $pass = ENCRYPTION_PASS,
string $cipher = 'aes-256-gcm'
): string {
// basic wachtwoord controle (minimaal 16 tekens)
if (strlen($pass) < 16) {
throw new InvalidArgumentException('Hewt wachtwoord moet minstens 16 tekens zijn.');
}
if (!in_array($cipher, openssl_get_cipher_methods())) {
throw new InvalidArgumentException("Cipher '{$cipher}' niet ondersteund.");
}
$ivLen = openssl_cipher_iv_length($cipher);
$iv = random_bytes($ivLen);
$tag = '';
$raw = openssl_encrypt(
$data,
$cipher,
$pass,
OPENSSL_RAW_DATA,
$iv,
$tag
);
if ($raw === false) {
throw new RuntimeException('Encryptie is mislukt.');
}
return base64_encode(json_encode([
'v' => base64_encode($raw), // value
'i' => base64_encode($iv), // iv
't' => base64_encode($tag), // tag
'c' => $cipher, // cipher
]));
}
public static function decrypt(string $blob, string $pass = ENCRYPTION_PASS): string
{
if (strlen($blob) < 30) {
return '';
}
$payload = json_decode(base64_decode($blob), true);
if (!$payload || !isset($payload['v'], $payload['i'], $payload['t'], $payload['c'])) {
return '';
}
return openssl_decrypt(
base64_decode($payload['v']),
$payload['c'],
$pass,
OPENSSL_RAW_DATA,
base64_decode($payload['i']),
$tag = base64_decode($payload['t'])
) ?: '';
}
public static function reEncrypt(
string $blob,
string $oldPass = ENCRYPTION_PASS,
string $newPass = ENCRYPTION_PASS,
string $cipher = 'aes-256-gcm'
): string {
$plain = self::decrypt($blob, $oldPass);
if ($plain === '') {
throw new RuntimeException('Kan data niet ontsleutelen met het oude wachtwoord.');
}
return self::encrypt($plain, $newPass, $cipher);
}
public static function isEncrypted(string $value): bool
{
if (strlen($value) < 30) {
return false;
}
$payload = json_decode(base64_decode($value), true);
return isset($payload['v'], $payload['i'], $payload['t'], $payload['c']);
}
}<?php
class clsFeedValue
{
// Return TRUE if value should be excluded
public static function exclude_StringStartsWith($sValue, $aValues = [])
{
foreach($aValues as $v)
{
if(clsString::startWith($sValue, $v))
{
return true;
}
}
return false;
}
public static function exclude_StringContainsAll($sValue, $aValues = [])
{
return clsString::containsAll($sValue, $aValues);
}
public static function exclude_StringContainsAny($sValue, $aValues = [])
{
return clsString::containsAny($sValue, $aValues);
}
public static function exclude_StringContainsNone($sValue, $aValues = [])
{
return clsString::containsNone($sValue, $aValues);
}
public static function exclude_StringEndsWith($sValue, $aValues = [])
{
foreach($aValues as $v)
{
if(clsString::endsWith($sValue, $v))
{
return true;
}
}
return false;
}
public static function exclude_StringIsEqualTo($sValue, $aValues = [])
{
foreach($aValues as $v)
{
if(clsString::isEqual($sValue, $v))
{
return true;
}
}
return false;
}
public static function exclude_StringIsEmpty($sValue, $aValues = [])
{
return is_empty($sValue);
}
public static function exclude_StringIsNotEmpty($sValue, $aValues = [])
{
return not_empty($sValue);
}
public static function exclude_NumberIsSmallerThen($sValue, $aValues = [])
{
if(is_empty($sValue))
{
return true;
}
elseif(is_empty($aValues[0] ?? ''))
{
return false;
}
return (clsString::toFloat($sValue) < clsString::toFloat($aValues[0]));
}
public static function exclude_NumberIsSmallerThenOrEqualTo($sValue, $aValues = [])
{
if(is_empty($sValue))
{
return true;
}
elseif(is_empty($aValues[0] ?? ''))
{
return false;
}
return (clsString::toFloat($sValue) <= clsString::toFloat($aValues[0]));
}
public static function exclude_NumberIsGreaterThen($sValue, $aValues = [])
{
if(is_empty($sValue))
{
return false;
}
elseif(is_empty($aValues[0] ?? ''))
{
return true;
}
return (clsString::toFloat($sValue) > clsString::toFloat($aValues[0]));
}
public static function exclude_NumberIsGreaterThenOrEqualTo($sValue, $aValues = [])
{
if(is_empty($sValue))
{
return false;
}
elseif(is_empty($aValues[0] ?? ''))
{
return true;
}
return (clsString::toFloat($sValue) >= clsString::toFloat($aValues[0]));
}
public static function exclude_NumberIsEqualTo($sValue, $aValues = [])
{
if(is_empty($sValue))
{
return false;
}
elseif(is_empty($aValues[0] ?? ''))
{
return false;
}
return (clsString::toFloat($sValue) == clsString::toFloat($aValues[0]));
}
public static function exclude_NumberIsEmpty($sValue, $aValues = [])
{
return is_empty($sValue);
}
public static function exclude_NumberIsNotEmpty($sValue, $aValues = [])
{
return !is_empty($sValue);
}
public static function exclude_NumberIsEmptyOrZero($sValue, $aValues = [])
{
return (is_empty($sValue) || is_zero($sValue));
}
public static function import_CleanupAvailability($sValue, $aParams = [])
{
if(is_numeric($sValue))
{
return (($sValue > 0) ? 'in_stock' : 'out_of_stock');
}
elseif($sValue = trim(preg_replace('([^a-z]+)', '_', strtolower($sValue)), '_'))
{
if(in_array($sValue, ['backorder', 'in_stock', 'out_of_stock', 'preorder']))
{
return $sValue;
}
elseif(in_array($sValue, ['false', 'no', '0']))
{
return 'out_of_stock';
}
}
return 'in_stock';
}
public static function import_CleanupCategories($sValue, $aParams = []) // Remove empty nodes
{
if($sValue = trim($sValue))
{
$sValue = str_replace('&', '&', $sValue);
$sValue = preg_replace('/^[0-9]+\s[\-]\s/', '', $sValue); // Strip Category ID (if any)
$sValue = str_replace(['>', '\\', '|', '>'], '/', $sValue); // Replace different seperator symbols
if(empty($aParams['seperator']))
{
$aParams['seperator'] = ' / ';
}
$aValue = explode('/', $sValue);
$aValue = array_map('trim', $aValue);
$aValue = array_filter($aValue);
$aValue = array_map('clsFeedValue::import_CleanupUppercaseWords', $aValue);
return implode($aParams['seperator'], $aValue);
}
return '';
}
public static function import_CleanupCategoryPath($sValue, $aParams = []) // Preserve empty nodes
{
if($sValue = trim($sValue))
{
$sValue = str_replace('&', '&', $sValue);
$sValue = preg_replace('/^[0-9]+\s[\-]\s/', '', $sValue); // Strip Category ID (if any)
$sValue = str_replace(['>', '\\', '|', '>'], '/', $sValue); // Replace different seperator symbols
if(empty($aParams['seperator']))
{
$aParams['seperator'] = ' / ';
}
$aValue = explode('/', $sValue);
$aValue = array_map('trim', $aValue);
// $aValue = array_filter($aValue);
$aValue = array_map('clsFeedValue::import_CleanupUppercaseWords', $aValue);
return implode($aParams['seperator'], $aValue);
}
return '';
}
public static function import_CleanupContent($sValue, $aParams = [])
{
return static::import_CleanupDescription($sValue, $aParams);
}
public static function import_CleanupDescription($sValue, $aParams = [])
{
if($sValue = trim($sValue))
{
$sValue = str_replace(TAB, SPACE, $sValue);
$sValue = str_replace(NBSP, ' ', $sValue);
if(strpos($sValue, '\n') !== false)
{
$sValue = str_replace([CRLF, CR, '\r\n', '\n', '\r'], CRLF, $sValue);
}
// Contains <HTML>?
if(clsSyntax::isHtml($sValue))
{
$sValue = clsString::removeHtml($sValue ?? '');
// Replace HTML parsing errors
$aSearch = ['&', '&', '&&'];
$aReplace = ['&', '&', '&'];
$sValue = str_replace($aSearch, $aReplace, $sValue);
// Replace special chars
$aSearch = ['à', 'á', 'â', 'ã', 'ä', 'å', '&aogon', 'æ', '&cacute', 'ç', 'è', 'é', 'ê', 'ë', '&eogon', 'ð', 'ì', 'í', 'î', 'ï', '&lstrok', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', '§', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', '&zacute', '&zdot', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', '&Aogon', 'Æ', '&Cacute', 'Ç', '©', 'È', 'É', 'Ê', 'Ë', '&Eogon', '&euro', 'Ð', 'Ì', 'Í', 'Î', 'Ï', '&Lstrok', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', '&oelig', '£', '§', '&trade', 'Ù', 'Ú', 'Û', 'Ü', '&dollar', 'Ý', '&Yuml', '&Zacute', '&Zdot', '&lowbar', '&grave', '&bdquo', '&hellip', '&OpenCurlyQuote', '&rsquo', '&OpenCurlyDoubleQuote', '&rdquo', '&ndash', '&mdash'];
$aReplace = ['à', 'á', 'â', 'ã', 'ä', 'å', 'ą', 'æ', 'ć', 'ç', 'è', 'é', 'ê', 'ë', 'ę', 'ð', 'ì', 'í', 'î', 'ï', 'ł', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', '§', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'ź', 'ż', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ą', 'Æ', 'Ć', 'Ç', '©', 'È', 'É', 'Ê', 'Ë', 'Ę', '€', 'Ð', 'Ì', 'Í', 'Î', 'Ï', 'Ł', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'œ', '£', '§', '™', 'Ù', 'Ú', 'Û', 'Ü', '$', 'Ý', 'Ÿ', 'Ź', 'Ż', '_', '', '„', '…', '‘', '’', '“', '”', '–', '—'];
$sValue = str_replace($aSearch, $aReplace, $sValue);
// Remove common special symbols
$aSearch = ['"', ''', '°', '&lsquo', ' ', '&rsquo', '®', '²'];
$aReplace = ['"', '\'', DEGREE, '"', '"', ' ', '®', '2'];
$sValue = str_replace($aSearch, $aReplace, $sValue);
}
$sValue = preg_replace('/[\r][\n][ ]+/', CRLF, $sValue);
$sValue = preg_replace('/[ ]+[\r][\n]/', CRLF, $sValue);
if($iOffset = mb_strpos($sValue, 'Reviews:'))
{
$sValue = mb_substr($sValue, 0, $iOffset);
}
while($iOffset = mb_strpos($sValue, '[embed]'))
{
if($iOffset2 = mb_strpos($sValue, '[/embed]', $iOffset))
{
$sValue = mb_substr($sValue, 0, $iOffset) . mb_substr($sValue, $iOffset2 + 8);
}
}
$sValue = trim($sValue);
$sValue = str_replace(CRLF . CRLF, CRLF, $sValue);
$sValue = static::import_CleanupUppercaseLines($sValue, $aParams);
$aParams['length'] = ($aParams['length'] ?? 5000);
$sValue = static::import_CleanupLength($sValue, $aParams);
}
return $sValue;
}
public static function import_CleanupGender($sValue, $aParams = [])
{
if($sValue)
{
$sValue = trim(strtolower($sValue));
if(in_array($sValue, ['male', 'm', 'man', 'b', 'boy']))
{
return 'male';
}
elseif(in_array($sValue, ['female', 'f', 'vrouw', 'g', 'girl']))
{
return 'female';
}
elseif(in_array($sValue, ['unisex']))
{
return 'unisex';
}
}
return '';
}
public static function import_CleanupGtin($sValue, $aParams = [])
{
if($sValue)
{
$sValue = str_ireplace('ean', '', $sValue);
$sValue = str_ireplace('gtin', '', $sValue);
$sValue = str_ireplace('sku', '', $sValue);
$sValue = str_ireplace('mpn', '', $sValue);
$sValue = preg_replace('/[^a-zA-Z0-9]+/', '', $sValue);
}
return ($sValue ?: '');
}
public static function import_CleanupLength($sValue, $aParams = [])
{
if($sValue && !empty($aParams['length']))
{
if(mb_strlen($sValue) > $aParams['length'])
{
if($iOffset = strrpos($sValue, ' ', $aParams['length']))
{
$sValue = trim(substr($sValue, 0, $iOffset), ' /-_:,;| ');
}
else
{
$sValue = trim(substr($sValue, 0, $aParams['length']), ' /-_:,;| ');
}
}
}
return $sValue;
}
public static function import_CleanupMpn($sValue, $aParams = [])
{
return ($sValue ?: '');
}
public static function import_CleanupPrice($sValue, $aParams = [])
{
if($sValue)
{
$sRegex = '/(([0-9]+)([\.,][0-9]+)*)/';
$aMatches = [];
if(preg_match_all($sRegex, $sValue, $aMatches))
{
return clsString::toFloat($aMatches[1][0], 2);
}
}
return '';
}
public static function import_CleanupSize($sValue, $aParams = [])
{
return $sValue;
}
public static function import_CleanupSku($sValue, $aParams = [])
{
return ($sValue ?: '');
}
public static function import_CleanupTitle($sValue, $aParams = [])
{
if($sValue = trim($sValue))
{
$sValue = str_replace(TAB, SPACE, $sValue);
// Contains <HTML>?
if(clsSyntax::isHtml($sValue))
{
$sValue = clsString::removeHtml($sValue ?? '');
// Replace HTML parsing errors
$aSearch = ['&', '&&'];
$aReplace = ['&', '&'];
$sValue = str_replace($aSearch, $aReplace, $sValue);