Een IBAN is een van de weinige identificatoren waarvan de interne grammatica volledig is gepubliceerd. Lees hem van links en je gaat door drie zones: een landcode, een paar controlecijfers en dan het nationale rekeningdeel. De eerste twee zones zijn overal hetzelfde, terwijl de derde van land tot land van vorm verandert.
Dat mengsel maakt de identificator zowel gemakkelijk te ontleden als gemakkelijk verkeerd te valideren. Dit artikel scheidt de delen, legt de mod-97-rekenkunde uit die ze bij elkaar houdt, en laat zien waarom de rekenkunde het minst interessante is dat de reeks te vertellen heeft.
Wat zijn de delen van een IBAN?
De naam staat voor international bank account number, en het ontwerpdoel was om één reeks genoeg informatie te laten dragen om een grensoverschrijdende overboeking te routeren zonder een apart instructieblad.
| Positie | Deel | Wie het definieert |
|---|---|---|
| Eerste twee tekens | Landcode | Een internationale standaardlijst van tweeletterige codes |
| Volgende twee tekens | Controlecijfers | De IBAN-norm zelf, identiek in elk land |
| Alles daarna | Nationaal rekeningdeel, vaak de BBAN genoemd | De nationale autoriteit van het betrokken land |
De landcode zegt welke nationale regels gelden; de twee cijfers zeggen of de reeks de overdracht intact heeft overleefd; de rest is de rekening zoals het land zelf hem schrijft. Alleen de middelste zone is gestandaardiseerd door de IBAN-regels, en alleen de middelste zone kan worden geverifieerd zonder de opzet van het land te kennen.
De voorbeelden die in dit artikel worden gebruikt zijn bewust synthetische plaatsvervangers, gekozen om te laten zien hoe de delen in elkaar passen. Geen ervan is een echte rekeningidentificator, en niets hier mag worden gelezen als een bewering dat een bepaalde rekening bestaat.
Landcode en de twee ISO-controlecijfers
De twee cijfers na de landcode komen uit een internationaal overeengekomen controletekenstelsel, de MOD 97-10-opzet die tot de familie behoort die in controlecijferalgoritmen wordt besproken. Omdat de rekenkunde de hele reeks in die twee posities opvouwt, maakt het wijzigen van een ander teken ze ongeldig.
Die eigenschap is de reden dat het paar de moeite van het berekenen waard is, zelfs wanneer de nationale opzet onbekend is. Een routine kan de eerste vier tekens tegen de rest van de reeks verifiëren en een conclusie bereiken over de integriteit van de overdracht zonder ook maar één nationale specificatie te bezitten. Wat hij niet kan, is beslissen of de lengte klopt voor het genoemde land, want die lengte leeft in de nationale regels.
Binnen die nationale regels verschillen de velden sterk. Het ene land kan een bankcode en een rekeningnummer in een vast aantal posities persen; het andere kan een filiaal, een valutamarkering of een nationaal controlecijfer toevoegen. De IBAN-norm legt vast hoe lang de hele reeks van elk land is, maar de betekenis van elk innerlijk veld blijft bij het land dat het heeft gedefinieerd.
Waarom draagt de BBAN vaak ook een nationaal controlecijfer?
Omdat het rekeningdeel meestal al lang een werkend nationaal nummer was voordat het in een grensoverschrijdend formaat werd ingebed. Banken hadden al hun eigen wacht tegen overtikfouten gebouwd, en de internationale wikkel verwijderde die niet. Het resultaat is een reeks die twee onafhankelijke controles draagt: het internationale paar vooraan en wat het land erin heeft gestopt.
De twee worden uit verschillend materiaal berekend, dus ze falen om verschillende redenen. Een beschadigde landcode breekt het internationale paar; een verkeerd getypt rekeningcijfer binnen het nationale deel kan ofwel de nationale controle, ofwel het internationale paar, ofwel beide breken, afhankelijk van waar het zit. Wanneer een validator meldt dat het formaat correct is maar de controle faalde, is de gebruikelijke verklaring dat het nationale deel en zijn controle niet meer overeenkomen.
Voor een implementator betekent dit dat dezelfde reeks op het ene niveau goed en op het andere fout kan zijn, en een melding die de twee samenvat is niet goed genoeg. Zeg welke controle faalde, en zeg welk deel van de reeks die dekt — de positie van het probleem is de informatie die de gebruiker nodig heeft.
Letters naar getallen omzetten: het idee achter mod-97
De rekenkunde heeft cijfers nodig, maar de reeks opent met letters. De brug is een substitutie: elke letter wordt volgens een vaste gepubliceerde regel door een getal vervangen, nadat de eerste vier tekens naar het einde van de reeks zijn verplaatst. De hele omgezette waarde wordt dan door zevenennegentig gedeeld, en een geldige identificator is er een die een specifieke rest overlaat.
Herschikken in plaats van toevoegen is het subtiele deel. De landcode en de controlecijfers naar achteren verplaatsen betekent dat de cijfers die worden geverifieerd aan het einde van het te delen getal zitten, zodat ze de rest rechtstreeks beïnvloeden. Dat is wat de twee voorste cijfers als controle op al het volgende laat werken.
Daaruit volgen twee gevolgen voor wie code schrijft. Ten eerste is de omgezette waarde veel langer dan welk gewoon geheel getaltype dan ook kan bevatten, dus de deling moet cijfer voor cijfer of met een big-number-voorziening worden uitgevoerd; pogingen om het met een gewone 64-bits geheel getal te doen overlopen stil en leveren onzin op bij sommige invoer. Ten tweede moeten letters met de exacte gepubliceerde omzetting worden geconverteerd — benaderingen zoals een alfabetische rang die bij één begint, geven een rest die plausibel lijkt en eenvoudigweg fout is.
Waarom bewijst een geslaagde controle niet dat een rekening bestaat?
De mod-97-rekenkunde vergelijkt de reeks met zichzelf. Ze heeft geen kennis van enige bank, enige klant of enige rekening, en niemand bij een uitgevende instelling wordt geraadpleegd wanneer ze draait. Een waarde kan perfect aan de rekenkunde voldoen en toch tot helemaal geen rekening behoren, want aan de rekenkunde voldoen is precies wat elke generator per ontwerp doet.
Verifiëren dat een rekening open en bereikbaar is, is een andere handeling met een ander kostenprofiel. Het vereist een opzoeking in een levend adresboek, dat snelheidsbeperkt kan zijn, buiten kantooruren onbeschikbaar kan zijn en überhaupt een contractuele relatie kan vereisen om te mogen aanroepen. Dat zijn de zorgen van een grens tussen client en server, niet van een checksum-routine.
De eerlijke foutmelding beschrijft daarom de reeks. Ze kan zeggen dat het formaat klopte en de controlecijfers standhielden, of dat de lengte niet past bij de opgegeven landcode. Ze mag niet zeggen dat de rekening bestaat, en ze mag niet suggereren dat een mislukte controle betekent dat de rekening gesloten of frauduleus is.
Voor ontwikkelaars: routeren op land en lengte
De implementatie is grotendeels boekhouding, en in de boekhouding zitten de bugs.
- Normaliseer de invoer eerst: verwijder spaties en streepjes en breng letters naar één vorm.
- Lees de landcode en zoek hem op. Is hij onbekend, meld dan een onbekend schema in plaats van een mislukte controle.
- Vergelijk de totale lengte met de lengte die het land definieert, en stop daar als ze niet overeenkomt — de rekenkunde is niet zinvol op een reeks van de verkeerde omvang.
- Voer de mod-97-transformatie uit en vergelijk de rest, met een cijfer-voor-cijfer- of big-number-routine.
- Verifieer elk nationaal controlecijfer binnen het rekeningdeel met zijn eigen regel.
Houd de landentabel als data bij, want lengtes en opzetten veranderen, en houd de twee uitspraken gescheiden in de retourwaarde: een niet-ondersteund land is geen ongeldige rekening. Waar een gebruiker een waarde plakt die uit een niet-vertrouwde bron komt, onthoud dan dat normalisatie presentatie verwijdert en niets anders; het is geen reparatiestap.
Volgende stappen
Neem een land dat je product ondersteunt, schrijf op wat zijn nationale opzet bevat, en herlees de reeks met dat in gedachten. Controleer dan een waarde van begin tot eind in de nummervalidatietool, en lees nummers zonder controlecijfer voor het tegenovergestelde geval, waarin een formaat het meeste is dat een validator ooit kan bevestigen.