Project: Wezan CIF-NL | Veilige datastromen binnen Fintech systemen
Plan van aanpak
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?
 
Organisatie: uitvoering door Wezan Enterprise BV in Meppel
 

Plan van aanpak – Veilige datastromen binnen Fintech-systemen

(focus op een PHP-back-end met MPC, Data Masking, DLP, sterke crypto en robuuste in en uitgaande data beveiliging)

1 Doel van de studie

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.

2 Scope

  • In scope

    • Gevoelige data­stromen tussen mobiele apps, onze web­portalen, micro backoffice services en backoffice services.

    • Verwerking en opslag in onze PHP core.

    • Veilige koppelingen met dataproviders, data­netwerken 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.

3 Compliance-kaders

  • PSD2 / RTS: sterke klantauthenticatie en secure communication.

  • AVG/GDPR: dataminimalisatie, rechtmatige verwerking, datalek­meldplicht.


4 Speerpunten & onderdelen


Elk onderdeel krijgt een Go / No Go op basis van: haalbaarheid qua performance, compatibiliteit en security.


1. Multiparty Compute (MPC) in PHP

  • 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.

2. Data Masking

  • Doel gevoelige gegeven afschermen in logs, dev-dumps en supportscreens.

  • Aanpak Dynamisch vervangen buiten productie (****1234) + statische mask.

  • Go = 100 % productie­data geanonimiseerd in niet produdctie omgevingen.

3. Data Loss Prevention (DLP)

  • Doel: Alle uitgaande bestanden & datapayloads scannen op Persoonlijk identificeerbare informatie (PII).

  • Aanpak:  Alerts naar security kanaal.

  • Go = geen onbedoelde gevoelige data in files.


4. Database beveiliging

  • Doel Elke endpoint voldoet aan “zero trust”.

  • Aanpak: logging inclusief userID en IP.

  • Go = 100 % testcases op succes


5. AES 256

  • Doel Alle gevoelige kolommen zoals persoonsgegevens versleuteld.

  • Aanpak Encryptie in combinatie met tags voor integriteits­check.

  • Go = succesvolle sleutel­rotatie zonder dataverlies.

6. RSA voor token signing & key uitwisseling

  • 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.

7. – ECC Curve device tot device encryptie

  • Doel Snellere en lichtere beveiliging voor mobiele clients.

  • Aanpak Hybrid schema: eerst ECIES, daarna AES.

  • Go = handshake < 1000 ms op 3G; 

5 Meetbare doelstellingen

  1. < 1 % onversleutelde PII in test en log­bestanden.

  2. < 10s extra latency door encryptie­lagen op kritieke data.

  3. 100 % API calls geauthenticeerd en gelogd met context (user, scope, IP).

  4. Automatische sleutelrotatie binnen 90 dagen zonder uitvaltijd.

  5. Maandelijks securityrapport met audittrails.

6 Benodigde middelen & vaardigheden

  • Technologie Nieuwe PHP code & key vault.

  • Team 4 senior PHP developers, 1 project manager

  • Training Crash-course MPC + ECC voor developers

 

7. Succescriteria (Go/No-Go)

  • Geen open findings bij interne pen-test.

  • Performance < 10 % op gemiddelde transactie­keten.

  • 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.

Marktonderzoek
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?

Marktonderzoek cybersecurity technieken voor veilige datastromen binnen fintech in PHP

1. Multiparty Compute (MPC)

Partisia MPC

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 MPC

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).

Conclusie MPC

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.


2. Data Masking

Microsoft Presidio

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 Data Masking

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.

Conclusie Data Masking

Er zijn tools beschikbaar, maar die zijn generiek en niet PHP native.

Zelf ontwikkelen is goedkoper, preciezer en beter afgestemd op onze behoeften.

3. Data Loss Prevention (DLP)

Symantec DLP

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.

Forcepoint DLP

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.

Microsoft Purview DLP

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.

Conclusie DLP

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.



4. API-beveiliging

Kong API Gateway

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.

Tyk API Gateway

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.

AWS API Gateway

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.

Conclusie API-beveiliging

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.


5. AES (Advanced Encryption Standard)

OpenSSL (via PHP)

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.

AWS KMS

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.

Conclusie AES

Gebruik OpenSSL in PHP is snel, veilig en zonder extra kosten. Geen reden om naar SaaS te gaan.


6. RSA (Rivest-Shamir-Adleman)

OpenSSL (PHP-extensie)

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.

AWS / GCP KMS

Beide bieden RSA key management via API.
Kosten: €1 per 10.000 encrypties + sleutelbeheer.

Voordelen:

  • Managed sleutelbeheer.
    Nadelen:

  • API latency.

  • Vendor lock in.

Conclusie RSA

OpenSSL in PHP is sneller, goedkoper en zonder lock in.

Geen voordeel in SaaS.


7. ECC (Elliptic Curve Cryptography)

OpenSSL ECC (PHP extensie)

ECC is ondersteund in PHP via OpenSSL.

Kosten: Gratis.

Voordelen:

  • Veiliger dan RSA met kleinere sleutels.

  • Geschikt voor signing.

    Nadelen:

  • Zelf sleutelbeheer regelen.

AWS / GCP KMS

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.

Conclusie ECC

OpenSSL via PHP is sneller en veiliger voor ons scenario. SaaS KMS voegt kosten en afhankelijkheid toe.


Conclusie marktonderzoek

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.

Risicoanalyse
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?

Risicoanalyse voor veilige datastromen binnen onze PHP-gebaseerde Fintechapplicaties

Inleiding

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.

Data Masking

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.

Secure Multi-Party Computation (MPC)

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.

 

Data Loss Prevention (DLP)

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.

API-beveiliging

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.

AES-encryptie

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. 

RSA-encryptie

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. 

ECC-encryptie

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.

 

2-EXP - Experimentele ontwikkeling - Ontwerp architectuur en gebruiksinterface
BIJLAGEN
Sandbox isolatie
Sandbox-isolatie van persoonsgegevens:

Data-inzameling (Data Suppliers)

Anonymisatie
Voordat de data de sandbox binnenkomt, worden de persoonsgegevens geanonimiseerd of gepseudonimiseerd.
Namen of ID’s worden omgezet in (bijv.) binaire waarden of generieke tokens.

Sandbox met sleutel-scrambling
Binnen de sandbox worden die tokens nog eens versleuteld of “gescrambled” met behulp van een geheime sleutel.
Daardoor krijgt elke data-set een unieke, onherleidbare code:

Hoewel het onderliggende token voor eenzelfde persoon identiek is in de sandbox, ziet elk fonds slechts zijn eigen versleutelde ID.
Zo kunnen fondsen onderling géén correlatie maken en wordt voorkomen dat iemand via matching aanvallen de echte identiteit herleidt.

Beveiligingsvoordelen

Gegevensisolatie: fondsen krijgen alleen de gepseudonimiseerde data, nooit de originele persoonsgegevens.

Toegangsbeheer: alleen de sandbox (en de verantwoordelijke beheerlaag) kent de scrambling-sleutel.

Verkleinen van risico’s: zelfs bij een lek binnen één fonds kunnen kwaadwillenden de data niet verbinden met de echte personen of met andere datasets.
Afbeelding downloaden
Data Masking Module
In dit diagram zie je hoe binnenkomende data via een “Data Access Wrapper” eerst bij de “Data Masking Module” terechtkomt. Via de “Configuration API” bepaalt de module welke velden gemaskeerd moeten worden. De gemaskeerde data gaat vervolgens door naar de productie-database, terwijl een (anonieme) log van de bewerkingen wordt weggeschreven in de “Logging Datastore”.
Afbeelding downloaden
Versleuteling met AES 256
Dit systeem ontwerp laat zien hoe we met AES-256 data veilig willen versleutelen en beheren in een batch-migratie:

App naar OpenSSL
De applicatie stuurt onversleutelde records naar OpenSSL, dat met de symmetrische sleutel uit een Key Vault de data versleutelt en er een integriteitstag bij maakt.

Taak­queue en migratieworker
De versleutelde payloads gaan in een taak­queue. Een migratieworker pakt deze taken op, schrijft de gecodeerde velden naar de database­kolommen en rapporteert succes of mislukking (via een beveiligd kanaal).

Key-rotatie en monitoring
Om de zoveel tijd roteert het systeem de AES-sleutels (rollende sleutel­rotatie). Het dashboard toont integriteits­tags en statussen, zodat je ziet of alles veilig én correct is gemigreerd.
Afbeelding downloaden
Database Validatie en logging
Elke inkomende query vanuit de app gaat eerst via een “pre-hook” naar de centrale validatielaag. Daar worden de verzoeken gecheckt op juiste credentials, rol, IP, enzovoort:

Geldige verzoeken krijgen een JSON-antwoord terug (met timestamp, user-ID, rol, IP) én worden gelogd in de centrale database.

Ongeldige of verdachte verzoeken triggeren meteen een alert, die zowel in de centrale database wordt weggeschreven als in het securitydashboard verschijnt.
Afbeelding downloaden
Authenticatie voor API Endpoints
Bij dit ontwerp verloopt de API-authenticatie in drie stappen:

Tokenaanvraag door de microservice
Een microservice (client) stuurt zijn identiteit (bijvoorbeeld een client-ID en geheim) naar de Token Service.

Tokenuitgifte en ondertekening
De Token Service haalt de juiste ondertekeningssleutels uit de Key Vault en genereert een JWT met drie delen:

Header (algoritme + token-type)

Payload (claims zoals client-ID, scopes, vervaldatum)

Signature (ECC of RSA, ondertekend met de vaultsleutel)

Audit logging
Elke uitgegeven of gevalideerde token wordt weggeschreven naar het Audit Log, zodat je precies kunt nagaan wanneer welke service welk token kreeg of gebruikte.

Met deze opzet hebben al je microservices een eenduidig, veilig en auditeerbaar mechanisme voor API toegang.
Afbeelding downloaden
Data Loss Preventie
Berichtstromen komen via een message broker binnen in een dedicated Data Loss Preventie Container, waar het volgende gebeurt:

Scannen van payload
De container pakt elk JSON- of XML-bericht en voert een content scan uit op gevoelige datapatronen (bv. creditcardnummers, persoonsgegevens).

Rule Engine
Aan de hand van een extern beheerd rules bestand beslist de rule engine of het bericht gevoelige info bevat die niet naar buiten mag.


Incident­melding

Voldoet het bericht niet aan de regels, dan wordt een incident gegenereerd en in een aparte Incident Queue geplaatst voor verdere afhandeling.

Voldoet het bericht wel, dan gaat het ongewijzigd door naar de achterliggende systemen, of wordt gemarkeerd als ‘goedgekeurd’.

Met deze opzet kun je centraal en configureerbaar gevoelige data in alle berichten detecteren, blokkeren of markeren, zonder de business­logica in je applicaties aan te passen.
Afbeelding downloaden
3-EXP - Experimentele ontwikkeling - Prototyping/iteratieve ontwikkeling
CODE SNIPPETS
Data Masking Module
Deze code voert data masking uit: gevoelige gegevens worden zo gewijzigd dat je er niets privacygevoeligs meer uit kunt afleiden, terwijl een herkenbaar “silhouet” intact blijft voor log- of UI-doeleinden.

Cybersecure waarde
AVG / GDPR-compliance:Je toont alleen de minimaal noodzakelijke delen van PII in foutmeldingen, logs of front-end-schermen.

Risk reduction: Mocht een logbestand uitlekken, dan bevat het geen complete e-mail­adressen of telefoonnummers die direct te herleiden zijn.

Consistent patroon: Een centrale functie voorkomt dat elke developer z’n eigen maskinglogica verzint (en fouten maakt).
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);
}
JWT Token & Validatie
elke keer dat iemand inlogt op onze applicatie drukken we een digitale toegangspas voor hem af. In die pas stoppen we niet alleen zijn naam en rechten, maar ook meteen een vervaldatum. Zo werkt het: op het moment dat de gebruiker zich meldt, smelten we de pas samen uit drie delen: een “voorblad” met de gekozen beveiligingsinstellingen, een “inhouds­opgave” met zijn gegevens en een onzichtbare handtekening eroverheen. Die handtekening berekenen we met SHA-512 én een geheim wachtwoord dat alleen de server kent.

Wanneer de pas later bij ons terugkomt, herhalen we precies dezelfde berekening en vergelijken we beide handtekeningen. Is er ook maar één letter veranderd of is de geldigheidsdatum verlopen, dan merken we dat onmiddellijk en sturen we de bezoeker vriendelijk maar beslist weer naar buiten. De truc is dat we nergens op de server hoeven bij te houden wie er allemaal binnen is; alle informatie die we nodig hebben reist veilig met de gebruiker mee. Dat scheelt geheugen, maakt de infrastructuur eenvoudiger en verkleint het aanvals­opper­vlak.

Dankzij de korte houdbaarheidsdatum blijft de schade bovendien beperkt mocht iemand de pas onderscheppen. Een kwaadwillige kan wel proberen de inhoud aan te passen of de geldigheid te verlengen, maar zonder ons geheime ingrediënt krijgt hij de handtekening nooit opnieuw kloppend. Zo combineren we snelheid en schaalbaarheid met een stevige beveiligings­laag, precies wat je nodig hebt als je bedrijf hard groeit en je klanten erop moeten kunnen vertrouwen dat hun data veilig is.
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;
}
API Data bescherming
Per resource/tabel kunnen per kolom regels worden vastgelegd hoe data beveiligd moet worden. Data kan worden ge-masked, hashed of encrypted.
Data kan ook worden geconverteerd naar andere format (datums, getallen, etc)
{
"columns": [
{
"name": "password",
"protection_function": "clsProtection::maskAll"
},
{
"name": "email",
"protection_function": "clsProtection::maskEmail"
},
{
"name": "phone",
"protection_function": "clsProtection::maskPhone"
}
]
}
API Data bescherming - Example Fetch
Zie onderstaand script als een korte rondleiding met een bezoekers badge:

Inchecken – We melden ons 1 keer bij de balie met gebruikersnaam en wachtwoord.

Badge krijgen – De server geeft ons een tijdelijke digitale pas.

Vragen wat we mogen zien – Met die pas hoort het script welke afdelingen (tabellen) voor ons openstaan.

Langs de afdelingen – We tonen even een paar taken, gebruikers en medewerkers; bij elke deur laten we de pas zien.


Waarom cybersecure?

Het wachtwoord reist maar 1 keer mee; daarna volstaat de pas.

De pas is kort houdbaar en kan altijd worden ingetrokken.

We krijgen alleen toegang tot wat bij deze pas hoort.

Kortom: 1 login, 1 badge, gecontroleerde toegang, simpel, snel en toch goed beschermd.
<?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"
}
]
Data versleuteling met AES 256
encrypt()

Controleert of het wachtwoord minstens 16 tekens is.

Versleutelt de tekst met AES 256

Verpakt de versleutelde data
{
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']);
}
}
Firewall voor binnenkomende data
firewall voor binnenkomende productdata.
Ze beslissen of een veld überhaupt mag worden opgeslagen


1. Excluders: poortwachters die verkeerde data buiten houden

Tekst checks

Begint met…, bevat allemaal…, bevat geen van…, eindigt op…, is exact gelijk aan…
Zo filteren we snel spamwoorden (“free bitcoin”) of ongewenste kreten voordat ze in onze database of ads komen.

Leeg of niet-leeg
Voorkomt dat we nullwaarden versturen naar onze database.

Getal-checks

kleiner dan, groter dan, gelijk aan, nul of leeg
Blokkeert onrealistische prijzen waarden.

Beveiligingswinst: minder kans dat een aanvaller via een feed kwaadaardige tekst, SQL/HTML-injecties of onjuiste prijzen door de keten sluist.


2. Cleanup-functies: alles wat door mag, eerst ontsmetten


Categorieën en paden

Verwijdert HTML-entiteiten, ID’s (“123 – …”) en dubieuze scheidingstekens.

Tekst wordt opgeschoond, hoofdletters netjes, onnodige lege niveaus verdwijnen.
Nuttig tegen XSS en voorkomt dat een malafide partner extra ­codes in sluist.

Omschrijving (import_CleanupDescription)

Haalt tabs, NBSP’s, dubbele enters, <script>-tags, rare HTML-entities, quotes-codes, embedded blocks en review-spam eruit.

Begrenst lengte en buigt CAPS-lock om.
Beschermt frontend-gebruikers tegen XSS en voorkomt dat we rommel naar platformen sturen.



3. Kleine helpers (gender, size, URL, etc.)
Uniformeren van waarden voorkomt dat downstream-services string-parsefouten krijgen en dat een aanvaller via exotische encodings of control-tekens ellende veroorzaakt.



Deze module met security functies is in feite een meerlaagse desinfectie­machine:

Eerst beslist ze of een invoer­waarde überhaupt welkom is.

Dan verwijdert ze alle troep, van HTML tot symbol-codes.

Tot slot dwingt ze strakke formats en lengtes af.

Daardoor komt er alleen schone, voorspelbare en veilige data onze systemen en de externe advertentie­platforms binnen. Dat verkleint het oppervlak voor aanvallen en voorkomt dure afkeuringen of reputatie­schade.
<?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('&amp;', '&', $sValue);
$sValue = preg_replace('/^[0-9]+\s[\-]\s/', '', $sValue); // Strip Category ID (if any)
$sValue = str_replace(['&gt;', '\\', '|', '>'], '/', $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('&amp;', '&', $sValue);
$sValue = preg_replace('/^[0-9]+\s[\-]\s/', '', $sValue); // Strip Category ID (if any)
$sValue = str_replace(['&gt;', '\\', '|', '>'], '/', $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 = ['&amp;', '&amp', '&&'];
$aReplace = ['&', '&', '&'];
$sValue = str_replace($aSearch, $aReplace, $sValue);

// Replace special chars
$aSearch = ['&agrave', '&aacute', '&acirc', '&atilde', '&auml', '&aring', '&aogon', '&aelig', '&cacute', '&ccedil', '&egrave', '&eacute', '&ecirc', '&euml', '&eogon', '&eth', '&igrave', '&iacute', '&icirc', '&iuml', '&lstrok', '&ntilde', '&ograve', '&oacute', '&ocirc', '&otilde', '&ouml', '&oslash', '&sect', '&ugrave', '&uacute', '&ucirc', '&uuml', '&yacute', '&yuml', '&zacute', '&zdot', '&Agrave', '&Aacute', '&Acirc', '&Atilde', '&Auml', '&Aring', '&Aogon', '&AElig', '&Cacute', '&Ccedil', '&copy', '&Egrave', '&Eacute', '&Ecirc', '&Euml', '&Eogon', '&euro', '&ETH', '&Igrave', '&Iacute', '&Icirc', '&Iuml', '&Lstrok', '&Ntilde', '&Ograve', '&Oacute', '&Ocirc', '&Otilde', '&Ouml', '&Oslash', '&oelig', '&pound', '&sect', '&trade', '&Ugrave', '&Uacute', '&Ucirc', '&Uuml', '&dollar', '&Yacute', '&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 = ['&#34', '&#39', '&deg', '&lsquo', '&nbsp', '&rsquo', '&reg', '&sup2'];
$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 = ['&amp', '&&'];
$aReplace = ['&', '&'];
$sValue = str_replace($aSearch, $aReplace, $sValue);
NCC-NL Dit project is uitgevoerd met subsidie uit de CIF-NL regeling van het ministerie van Economische Zaken en Klimaat, uitgevoerd door de Rijksdienst voor Ondernemend Nederland