Country-specific checksums
globalcitizen opened this issue · 50 comments
We could support the calculation of known national (BBAN-level) or bank-specific (sub-BBAN-level) checksums against algorithms where known. Please contribute if you know any.
Fun, fun, fun
Zero or more checksum digits
In some cases like the Netherlands (and perhaps French SIREN), there are no checksum digits but an algorithm exists anyway. About half of the countries have 1 checksum digit, and about half have 2.
Types of algorithms
In some cases like Spain, we see a single check digit applied to part of the BBAN, and a second check digit applied to the rest of the BBAN.
Normally however, the checksum should be applied to the whole BBAN minus the checksum itself, or possibly with the checksum zeroed (where this is significant) or the checksum replaced with 'XX' (where this is logical).
Newer countries almost certainly use an ISO7064 variant. Unfortunately, the ISO insists on charging for its standards, so we can't get a copy. In addition, there are actually two ISO7064 standards, a 1983 version and a 2003 version. Probably the older countries use the 1983 version. What differences exist are unclear. If someone would like to donate me copies of either standard, that would be useful. According to the ISO7064 java library, ISO7064 defines the following 'pure' systems, each of which use a single modulus for all stages of the calculation:
- ISO/IEC 7064, MOD 11-2 for numeric strings with one check digit or the supplementary check character "X"
- ISO/IEC 7064, MOD 37-2 for alphanumeric strings with one check digit or letter or the supplementary check character "*"
- ISO/IEC 7064, MOD 97-10 for numeric strings with two check digits
- ISO/IEC 7064, MOD 661-26 for alphabetic strings with two check letters
- ISO/IEC 7064, MOD 1271-36 for alphanumeric strings with two check digits or letters
In addition, it also defines the following 'hybrid' systems (not implemented by the library). The hybrid systems each use two moduli in the calculation. One modulus is equal to, and the other is one greater than, the number of characters in the character set of the string to be protected. These hybrid systems always provide a check character within the character set of the string to be protected:
- ISO/IEC 7064, MOD 11,10 for numeric strings with one check digit
- ISO/IEC 7064, MOD 27,26 for alphabetic strings with one check letter
- ISO/IEC 7064, MOD 37,36 for alphanumeric strings with one check digit or letter
There are also three other major algorithms:
- Luhn algorithm (1954) - for numeric strings with one check digit, based on mod10
- Verhoeff algorithm (1969) - for numeric strings with one check digit, complex, based on lookup tables
- Damm algorithm (2004) - for numeric strings with one check digit, complex and rare, based on weakly totally anti-symmetric quasigroups.
Summary of Algorithms
Algorithm | Input type | Output characters | Basis | References | Comments |
---|---|---|---|---|---|
ISO/IEC 7064, MOD 11-2 | Numeric | 1 digit/X |
Mod11 Radix 2 | java | |
ISO/IEC 7064, MOD 37-2 | Alphanumeric | 1 digit/letter/* |
Mod37 Radix 2 | java | |
ISO/IEC 7064, MOD 97-10 | Numeric | 2 digits | Mod97 Radix 10 | java | |
ISO/IEC 7064, MOD 661-26 | Alphabetic | 2 letters | Mod661 Radix 26 | java | Unlikely. |
ISO/IEC 7064, MOD 1271-36 | Alphanumeric | 2 digits or letters | Mod 1271 Radix 36 | java | |
ISO/IEC 7064, MOD 11,10 | Numeric | 1 digit | Hybrid | ||
ISO/IEC 7064, MOD 27,26 | Alphabetic | 1 letter | Hybrid | Unlikely | |
ISO/IEC 7064, MOD 37,36 | Alphanumeric | 1 digit/letter | Hybrid | ||
Luhn | Numeric | 1 digit | Mod10 | ||
Verhoeff | Numeric | 1 digit | Complex | ||
Damm | Numeric | 1 digit | Complex |
Automation
Which system is in use should be possible to determine even without offficial documentation through reverse engineering given a sufficient number of real world account number examples. So, please contribute real world example BBANs for each of these countries.
I am working on developing a utility to automatically construct various inputs to various algorithms and test them for a given IBAN. This should help us to detect the correct implementation for new countries. The properties of a given country's input that can be automatically determined are:
- Number of output check digits/characters (0, 1 or 2)
- Check digits (
0
-9
only) or check characters? (ie. may includeX
orA-Z
) - The various potential inputs (bank/branch portion, account portion), with checksum places removed or zeroed
So far I have ported the Java implementation to PHP using code generation, gathered working implementations of the final three algorithms, and written a general testing utility.
Countries with apparent national checksum systems
Data here is combined from Wikipedia, SWIFT official registry sources, random code and hearsay. We are looking to get solid references wherever possible, and in other cases to validate by reverse engineering a sufficient number of BBANs.
Country | IBAN Format (x=checksum) | Digits | Algorithm | References | Done |
---|---|---|---|---|---|
Albania | ALkk bbbs sssx cccc cccc cccc cccc | 1 | Luhn(bank+branch) | Reversed | ✔ |
Belgium | BEkk bbbc cccc ccxx | 2 | No-pad MOD97 bbbc cccc cc |
hearsay, OCM | ✔ |
Bosnia | BAkk bbbs sscc cccc ccxx | 2 | ? | official | |
East Timor | TLkk bbbc cccc cccc cccc cxx | 2 | ISO7064-MOD97-10 | official + 2nd | ✔ |
Estonia | EEkk bbss cccc cccc cccx | 1 | ? | official doesn't work. Alternate supplied below. | |
Faroe Islands | FOkk bbbb cccc cccc cx | 1 | ? | Banks not responding to emails. | |
Finland | FIkk bbbb bbcc cccc cx | 1 | ? | validate-only code, finnish-hearsay, finnish-other, OCM | |
France | FRkk bbbb bggg ggcc cccc cccc cxx | 2 | Two systems: RIB=MOD97 (EBCDIC+pad+concat) SIREN=sum/10=0 |
hearsay, OCM | ✔ |
Hungary | HUkk bbbs sssk cccc cccc cccc cccx | 1 | ? | ? | |
Italy | ITkk xaaa aabb bbbc cccc cccc ccc | [A-Z]{1} | Custom | pdf pp82-84 OCM (not this) Details supplied below. |
✔ |
Luxembourg | LUkk cccc cccc cccc xx | 2 | ? | OCM | |
Macedonia | MKkk bbbc cccc cccc cxx | 2 | ISO7064-MOD97-10 | Reversed | ✔ |
Mauritania | MRkk bbbb bsss sscc cccc cccc cxx | 2 | ? | ||
Monaco | MCkk bbbb bsss sscc cccc cccc cxx | 2 | Same as France. | @gaetan-be | ✔ |
Montenegro | MEkk bbbc cccc cccc cccc xx | 2 | ISO7064-MOD97-10 | Reversed | ✔ |
Netherlands | NLkk bbbb cccc cccc cc | 0 | MOD11(account) | Reversed. hearsay, OCM. Exception: INGB |
✔ |
Norway | NOkk bbbb cccc ccx | 1 | Custom MOD11 | OCM | ✔ |
Poland | PLkk bbbs sssx cccc cccc cccc cccc | 1 | ? | ? | |
Portugal | PTkk bbbb ssss cccc cccc cccx x | 2 | ISO7064-MOD97-10 | hearsay, OCM | ✔ |
San Marino | SMkk xaaa aabb bbbc cccc cccc ccc | [A-Z]{1} | ? | ||
Serbia | RSkk bbbc cccc cccc cccc xx | 2 | ISO7064-MOD97-10 | official, Wikipedia | ✔ |
Slovenia | SIkk bbss sccc cccc cxx | 2 | ISO7064-MOD97-10 | Reversed | ✔ |
Spain | ESkk bbbb gggg xxcc cccc cccc | 2 | MOD11 | OCM, Wikipedia | ✔ |
Sweden | SEkk bbb c cccc cccc cccc ccx | 1 | ? | hearsay |
Other situations
Code | Country | Situation |
---|---|---|
AT | Austria | Many, many bank-specific checksum schemes. (hearsay) |
DE | Germany | Many, many bank-specific checksum schemes. (source) |
CH | Switzerland | Some evidence of bank-specific legacy checksum schemes. (hearsay) |
@dem3trio @gaetan-be I've cleaned up this issue and did a fair bit of work yesterday. Still looking for help with remnants.
Monaco is the same system as France
Example IBAN: MC1112739000700011111000h79
RIB = 12739000700011111000h
Checksum = 79
Checked against
http://marlot.org/util/calcul-de-la-cle-rib.php
BTW, did you debug the BE BBAN issue you had? I saw there was 1 digit missing in the BBAN, hence your wrong checksum calculation.
Thanks for the tip on Monaco, seems to work, released as v2.4.8.
[BE (IANA:.be, ISO3166-1 alpha-2:BE): Belgium]
Is a SEPA member? Yes.
Example IBAN: BE68 5390 0754 7034
- country BE
- checksum 68
- bban 539007547034
- bank 539
- branch
- account 007547034
- natcksum 34
(National checksum manually validated.)
(National checksum automatically validated.)
(Correction of national checksum functionality validated.)
Looks fine to me, that's the BE output from utils/test.php
I've emailed the Danish National Bank about the Faroe Islands system (and to confirm that Denmark had no such pre-IBAN nation-wide domestic checksum scheme) and hope they will respond this week.
We should probably email the others also.
Their reply: "My recommendation to you will be to ask the Danish Bankers Association ('Finansraadet' in Danish) cf. this link http://www.finansraadet.dk/en/Pages/mainpage.aspx or alternatively one of the Faroese bank directly e.g. Eik Banki, www.eik.fo or Nordoya Sparikassi P/F, www.ns.fo."
I have emailed all of them, as well as this other one. A Finnish bank appears to have a branch there, but I figured they probably haven't been around as long as the others so weren't worth asking.
Also wrote to the Bank of Greenland to verify whether any historic national checksum scheme existed.
The Netherlands (NL) bank INGB
IBANs in the test set I gathered were all failing national checksums, yet are real world IBANs. It seems INGB
has been leading the migration away from the previous national checksum scheme. In v2.4.15 a check has been added which returns '' (unimplemented/no known national checksum scheme) when input is determined to derive from the INGB
bank. This marks our first bank-specific checksum feature.
Bank of Slovenia is bank 01
in Slovenia (SI) and has a similar national checksum special case exception. Released in v2.4.17.
Phew, OK I've searched out a good number of real world example IBANs for all of these countries and committed them under utils/example-ibans/
. Based upon testing against those, I've removed a lot of false assumptions about national systems and released a well tested version, v2.5.0.
Multiple banks of FO
did not respond. I think I am going to leave this as 'help wanted' and stop putting effort in, unless people start contributing I'm not sure how much further I can be motivated to go.
I just came over this issue while searching how to calculate Estonian BBAN national check digit. I found a better link that explains the algorithm correctly: http://www.pangaliit.ee/en/settlements-and-standards/example-of-the-use-of-method-7-3-1 (the example PHP code is still invalid)
As an example I implemented it in JavaScript to verify:
var validIban = "EE731010220027689012";
var validBban = validIban.substring(4);
// National Check Digit is calculated on the account number only "EE7310[1022002768901]2"
var accountNumber = validBban.substring(2, validBban.length - 1);
var checkDigit = "101022002768901"
// Convert it to array of numbers
.split("").map(Number)
// 7-3-1 are mapped and multiplied from right-to-left
.reverse().map((val, index) => ([7,3,1][index % 3] * val))
// the results are summed
.reduce((val, previous) => { return val + previous; }, 0)
// the result is subtrackted from the next nearest multiple of 10
% 10 * -1 + 10; // == 2
Sorry for not having interest for further contribution.
@vellotis Thanks for taking the time to contribute. The information may be utilized in a future update.
UK standards are here: https://www.vocalink.com/customer-support/modulus-checking/
Short summary is that schemes vary by bank (and sometimes branches within each bank), and are not mandatory
I was going to comment on Estonia, same thing as @vellotis. NVM about Italy.
This issue actually helps me a lot, using node for my implementation.
this is an italian program documentation that explain how CIN and CHECK DIGIT works:
http://www.artico.name/soft/iban/wiban.htm#cin
this is a javascript based tool for check and verify italian iban:
http://www.m8k.org/tracciatocbinet/iban.php?dahome=s
@xMase Thanks a lot! I will try to get around to translating and integrating this soon.
@globalcitizen If you need help do not hesitate to contact me
Your summary indicates Albanian bank codes having Luhn-10 checksum, but based on the following website (which lists "20311003", "20311027", "20311010", etc. as BICs), I'm not sure the assumption is always valid:
https://www.uba.com.al/index.php?option=com_content&view=article&id=65&lang=en&Itemid=612
@rlecour According to previous research the final digit of those bank and branch identification codes (in my opinion it's not a good idea to call them BICs as that is a specific term used in the SWIFT network) is the Luhn check. As such, there is nothing unexpected here. However, thanks for contributing another English language source.
About Italian BBAN checksum, the only official document I've found (so far) is here: http://www.cnb.cz/cs/platebni_styk/iban/download/TR201.pdf , page 81.
Hope to find more.
As you note in the table, Germany has multiple flavours (including "none") chosen by each bank. Detailed specifications here
I've just created a quick-and-dirty translation of Italian BBAN checksum computation here: https://gist.github.com/francescozanoni/6489e64d22e54acaa55dd09773ca458d.
The original was in Visual Basic (properly referenced).
@francescozanoni Thanks. I am quite busy today but if you like you could try forking the repository, adding a new function to php-iban.php
and refactoring the code you just provided to the standard function-based interface we use in php-iban, then submitting a pull request. The function should look something like ...
# Implement the national checksum for an Italian (IT) IBAN
function _iban_nationalchecksum_implementation_it($iban,$mode) {
# first, extract the BBAN
$bban = iban_get_bban_part($iban);
# actual implementation
#(here you should calculate $expected_nationalchecksum from the code you provided)
# return result
if($mode=='find') {
return $expected_nationalchecksum;
}
elseif($mode=='set') {
return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
}
elseif($mode=='verify') {
return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
}
}
v2.6.8 released - added national checksum implementation for Italy (IT
) thanks to @francescozanoni
Hi, man.
According to http://www.cnb.cz/cs/platebni_styk/iban/download/TR201.pdf at page 96 and to https://www.abbl.lu/topic/iban-and-bic-codes/, Luxembourg has no national checksum within BBAN.
Thanks for organizing all this info in one place, it's quite helpful!
I just came across an official reference for Albania: https://www.bankofalbania.org/rc/doc/Regulation_no_42_On_the_Structure_and_the_Use_of_the_International_Bank_Account_Number_IBAN_3422_2_6127.pdf (see Annex 4 footnote 1):
Algorithm for module 10: S8 = 10 – (S1 * 9 + S2 * 7 + S3 * 3 + S4 * 1 + S5 * 9 + S6 * 7 + S7 * 3) MOD10
where S is the digit value of n-te n of BIC.
Tried it on one example I have, and it works.
@amichair Awesome, thanks! Feel free to submit a patch. Try it out with the test scripts and add any extra Albanian example IBANs you can see.
And if I understand this correctly, Bosnia uses the standard ISO7064-MOD97-1
https://www.cbbh.ba/Content/Read/610?title=The-Instruction-on-the-structure-and-use-of-International-Number-of-the-Bank-Account-(IBAN)---Published-in-the-Official-Gazette-of-Republika-Srpska
I'm currently not working on perl and don't have much spare time to set it up... but at least the reference is here for the next time someone needs it :-) I find most of the effort is in hunting down the specs, whereas implementations are pretty simple.
Reversed Estonia algorithm from this official-looking js calculator and this code from their IBAN calculator page, both of which have pretty horrible code style :-)
The calculation seems to exclude the 2-digit bank identifier, i.e. it starts at offset 6 of the IBAN. Each digit is multiplied by a respective factor in the sequence 7,1,3,7,1,3,7,1,3...., the products summed up, and modulo 10 applied to the sum. The check digit is the complement to 10 (i.e. 10 - modulus, except if modulus is 0 in which case the check digit is 0). Note that the original code iterates over the digits from end to start, presumably in order to support a variable number of leading zeros, however in the IBAN it's always a fixed size calculation so you can do it in natural order as well.
Tried on 3 IBANs I found in different places, all pass.
Also, https://www.ecbs.org/Download/Tr201v3.9.pdf
(official document containing various national check digits schemes).
Mauritania appears to use a variant of ISO7064-MOD97-10 where the result is subtracted from 97 instead of 98 (i.e. the validated checksum is 0 rather than 1). Tested on the registry's example plus two googled real IBANs.
btw once updated perhaps some version of the table above should be added to the IBAN wikipedia page, if they'd accept it...
The only reference to Poland I found is here, had to search for it in Polish (which I do not speak). Works on 3 examples I found. Uses the weights 3, 9, 7, 1, 3, 9, 7 and modulo 10.
San Marino is the same as Italy (https://www.ecbs.org/Download/Tr201v3.9.pdf).
Awesome detective work @amichair! Unfortunately personally I am extremely busy (never this busy in my life) and unable to allocate enough time right now but will get around to it eventually if nobody else contributes.
PS. Examples over here - https://github.com/globalcitizen/php-iban/tree/master/utils/example-ibans
Last one to wrap it up (I hope) - Finland uses Luhn's. Taken from the Validate_FI code linked above, but without all the account number manipulations that are not needed since in the IBAN it's already expanded to 14 digits, so all that's left is to run Luhn's.
My code (based on my previous comments above) now supports all of the countries in the table above, and all of your example ibans (thanks for the link!) pass validation after removing the various junk punctuation characters.
Yay!
Thanks @amichair - far and away best research contribution ever :)
Summed up all of the research and algorithms here:
https://en.wikipedia.org/wiki/International_Bank_Account_Number#National_Check_Digits
In Hungary: https://farkasdezso.hu/bankszamlaszam/
For what I deduced Bosnian national checksum exists only so that "global"/standard checksum will always be 39.
The links for East timor work no longer
@Vulwsztyn Bosnia isn't the only one with that property. It's been awhile since I looked at it but IIRC you get that behavior when the national checksum locks the IBAN checksum at a fixed value. For East Timor try http://web.archive.org/ .. feel free to submit a pull request.
Leaving a comment here to help myself remember which countries, that I looked into, use a national checksum and which method they use. If a country is already added to php-iban
but not in this list, is because I didn't looked into it yet.
Country | IBAN format | Digits | Algorithm | References |
---|---|---|---|---|
Albania | ALkk bbbs sssx cccc cccc cccc cccc | 1 | Weighted | Official, Official (2nd) |
Angola | AOkk bbbb ssss cccc cccc cccx x | 2 | MOD 97-10 | EduBanca |
Bosnia | BAkk bbbs sscc cccc ccxx | 2 | MOD 97-10 | Official |
Belgium | BEkk bbbc cccc ccxx | 2 | MOD 97 | OCM, Wisfaq |
Burkina Faso | BFkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Burundi | BIkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Benin | BJkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Central African Republic | CFkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Congo | CGkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Ivory Coast | CIkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Cameroon | CMkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Cape Verde | CVkk bbbb ssss cccc cccc cccx x | 2 | MOD 97-10 | |
Czech Republic | CZkk bbbb cccc cxcc cccc cccx | 2x1 | Weighted | Official calculator |
Djibouti | DJkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Algeria | DZkk bbbb bsss sscc cccc cccc xx | 2 | MOD 97 | Official |
Estonia | EEkk bbss cccc cccc cccx | 1 | Weighted | Official, Official calculator, Official converter (PHP), ECBS |
Spain | ESkk bbbb ssss xxcc cccc cccc | 2 | Weighted | ECBS, OCM |
Finland | FIkk bbbb bbcc cccc cx | 1 | Luhn | ECBS, OCM |
France | FRkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | OCM, ECBS |
Gabon | GAkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Equatorial Guinea | GQkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Croatia | HRkk bbbb bbxc cccc cccc x | 2x1 | MOD 11-10 | ECBS |
Hungary | HUkk bbbb bbbx cccc cccc cccc cccx | 2x1 | Weighted | ECBS |
Iceland | ISkk bbss ttcc cccc cccc cccc xc | 1 | Weighted | OCM, ECBS |
Mali | MLkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Niger | NEkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Senegal | SNkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
Chad | TDkk bbbb bsss sscc cccc cccc cxx | 2 | MOD 97 | Uses the same as France |
Togo | TGkk bbbb bsss sscc cccc cccc ccxx | 2 | MOD 97 | Combination of Algeria and France |
The following countries don't provide any national checksum
Country | IBAN format | References |
---|---|---|
Andorra | ADkk bbbb ssss cccc cccc cccc | Official |
United Arab Emirates | AEkk bbbc cccc cccc cccc ccc | Official |
Azerbaijan | AZkk bbbb cccc cccc cccc cccc cccc | Official |
Bulgaria | BGkk bbbb ssss ttcc cccc cc | ECBS |
Bahrain | BHkk bbbb cccc cccc cccc cc | Official |
Brazil | BRkk bbbb bbbb ssss sccc cccc ccct n | Official |
Belarus | BYkk bbbb aaaa cccc cccc cccc cccc | Could not access site |
Costa Rica | CRkk 0bbb cccc cccc cccc cc | Official |
Cyprus | CYkk bbbs ssss cccc cccc cccc cccc | |
Dominican Republic | DOkk bbbb cccc cccc cccc cccc cccc | |
Egypt | EGkk bbbb ssss cccc cccc cccc cccc c | EG Bank |
Georgia | GEkk bbcc cccc cccc cccc cc | Official, Official validator |
Guatemala | GTkk bbbb mmtt cccc cccc cccc cccc | Official |
Israel | ISkk bbbs sscc cccc cccc ccc | |
Iraq | IQkk bbbb sssc cccc cccc ccc | |
Iran | IRkk 0bbt cccc cccc cccc cccc cc |
Other situations
Country | IBAN format | References |
---|---|---|
Austria | ATkk bbbb bccc cccc cccc | Multiple checksum calculations. (ECBS) |
Switzerland | CHkk bbbb bccc cccc cccc c | Multiple checksum calculations. (ECBS) |
Germany | DEkk bbbb bbbb cccc cccc cc | Multiple checksum calculations. (Official, ECBS) |
Denmark | DKkk bbbb cccc cccc cx | Has a checksum and found some methods, but doesn't work for all IBANs I gathered. (MyPlace) |
Faroe Islands | FOkk bbbb cccc cccc cx | Uses the same a Denmark |
United Kingdom | GBkk bbbb ssss sscc cccc cc | Multiple checksum calculations (VocaLink) |
Gibraltar | GIkk bbbb cccc cccc cccc ccc | Multiple checksum calculations (ECBS) |
Greenland | GLkk bbbb cccc cccc cx | Uses the same a Denmark |
Greece | GRkk bbbs sssc cccc cccc cccc ccc | Multiple checksum calculations. (ECBS) |
Ireland | IEkk bbbb ssss sscc cccc cc | Multiple checksum calculations |
Just a reminder, after looking up and verifying everything I could find from here and elsewhere (a few days of research), all the results were updated in the wikipedia page linked above... it would be great if anyone having updates (backed by as authoritative references as possible) could also update the wikipedia tables for the benefit of the world at large :-)
Thanks!
I found the checksum for Croatia, or should I say both of them. Croatia uses 2 checksums. The first one uses MOD11-10 for the bank code (seven digits) and the second one also uses MOD11-10 for the account number (ten digits).
I already wrote the algorithm for the checksums, but I want your advice on how I should return them.
- The
verify
mode will be easy to implement. If both of them are the same, returntrue
; otherwisefalse
. - The
find
mode should also be easy to implement. I just need to know how you want it to be returned?- Both values separately
- As one string (ex:
Bank: x - Account: x
) - As an array
- The
set
mode is easy to implement. Will probably need to write a new function to replace both values.
I would like your input on how to return the results to the user.
Great work!
Realistically this is an outlier and the number of people who will use both algorithms independently is minimal.
I propose returning the account number checksum only from the existing find
method.
However, implementing both algorithms in verify
and set
would be great.
Documentation will need to be updated to explain this behaviour.
With these reasonable defaults and documentation, I think the edge-case of people having an IBAN passing one national checksum algorithm and failing the other for Croatia can be ignored in the general implementation as unlikely.
Found another special case: Estonia.
Estonia has a checksum that is calculated via a weighted MOD 10 using the BBAN (4-14 digits). Another check it uses is that the BBAN has to begin with the bank code and has a specific length per bank code.
Following the steps from the converter (see references):
- Check if the bban is valid
- Check that the bban is between 4 and 14 digits
- Check that the bank code exists and that the bban has the correct length (differs per bank)
- Check that the bban has the correct national checksum (weights: 7, 3, 1)
- Check that the bank code in the bban exists
- Pad the bban to 14 digits
- Calculate the iban checksum
- Create iban
- Add country code (EE)
- Add checksum (00)
- Add bank code (ex. 22)
- Add bban (ex. 00221001121961)
- Calculate checksum
- Create iban
Examples of the structure for the IBANs and BBANs
Country | Checksum | Bank code | Pad | BBAN |
---|---|---|---|---|
EE | 75 | 22 | 00 | 221001121961 |
EE | 48 | 17 | 000 | 17000107462 |
EE | 19 | 10 | 10220028966019 | |
EE | 65 | 42 | 0 | 4207004188303 |
Using the BBANs from above
Bank code | Pad | Account number | Checksum |
---|---|---|---|
22 | 100112196 | 1 | |
17 | 000 | 10746 | 2 |
10 | 22002896601 | 9 | |
42 | 0 | 700418830 | 3 |
The bank code at the beginning of the BBAN is placed in front of the BBAN when creating the IBAN.
References:
@globalcitizen What should I implement in the algorithm? Just the validation of the checksum or also the validation of the bank code and bban?
Another related question: Some countries use a hardcoded iban checksum (most African countries), do I need to modify the implementations to also check for these to prevent malformed IBANs?
@Olympic1 Can you clarify how this differs from the Estonia entries on the wikipedia page?
@Olympic1 Can you clarify how this differs from the Estonia entries on the wikipedia page?
It doesn't have any differences, I found the same references as on the wiki. I'm just asking what I should implement for the validation function.
Thanks for your continued efforts.
@globalcitizen What should I implement in the algorithm? Just the validation of the checksum or also the validation of the bank code and bban?
Bank codes are always changing and really need to be considered out of scope for this project. It would be great if we could one day add them as a separate database but realistically it's not going to happen because the data is sold and never really up to date even from the 'official' sources, I believe.
That said, the national checksum implementations are pretty edge-case anyway. I think most users of this library do not use them. However, they really are useful in some cases and I believe we are the best source for them right now. In answer to your question:
- As far as a national implementation goes, the algorithm is definitely the most important.
- In addition to that, if you can find an authoritative source suggesting strongly that it won't generate false results and do the leg-work, I'm not opposed to a regex-based validation using known account number length information per bank code, eg.
^(?:bank1|bank2|bank3)$
where bank1 might beBANK1CODEHERE[0-9]{12}
or similar and this allows both the code and a corresponding length to be checked.
Another related question: Some countries use a hardcoded iban checksum (most African countries), do I need to modify the implementations to also check for these to prevent malformed IBANs?
In my experience these are not hard-coded, rather the existing pre-IBAN national checksum system provides a stable basis for the IBAN checksum algorithm, thus it winds up always being the same value. There is no adequate reason to corrupt the "IBAN checksum should always be validated" (existing/good/cautious) behaviour for the sole sake of saving a few CPU cycles on these cases, and I can't see any other benefit.