iban.pizza

Check digits

German account check digit methods and the rule that governs them.

The Bundesbank assigns every German bank code a check digit method identifier and publishes about ninety algorithms in pruefzifferberechnungsmethoden-data.pdf. The identifier travels with the bank record, so a lookup already knows which method applies to an account.

The upstream project parsed that identifier, stored it in its database, and never implemented a single method. Account numbers were therefore never checked.

The rule that governs this package

An unverified method reports "unchecked", never "invalid".

Rejecting a valid customer account is far worse than admitting that nothing was checked. The consequences follow from that:

  • A method with no implementation returns ResultUnchecked.
  • A method with an implementation but no official test vectors also returns ResultUnchecked, because nothing proves the implementation correct.
  • The API renders unchecked as "ok": null, which does not count against the overall valid.

Implemented and verified

Eleven methods are implemented and confirmed against the test account numbers printed in the specification. TestOfficialVectors runs every published vector on every build.

MethodRuleShare of German institutions
09No calculation is prescribed, so nothing is ever claimed20.2%
00Modulus 10, weights 2 and 1, digit sum of products9.4%
88Modulus 11 over positions 4 to 9, with a rule for a leading 98.2%
06Modulus 11, weights 2 to 77.8%
10Modulus 11, weights 2 to 105.6%
32Modulus 11 over positions 4 to 94.6%
28Modulus 11 over positions 1 to 73.9%
34Method 28 with weights 2, 4, 8, 5, 10, 9, 73.5%
99Method 06 with an exempt account range2.9%
17Modulus 11 over the customer number, left to right
C1Two variants selected by the first digit, using method 17

Method C1 is ING-DiBa's. It is included despite its low share of institutions because the bank behind it is large, and it has twenty published vectors covering both variants and both outcomes.

Implemented but held back

Methods 01, 02 and 13 have an implementation derived from the specification text, but the document publishes no test account numbers for them. They are listed in methods and excluded from verified, so they report unchecked.

Method 13 alone covers about 7.5 percent of German institutions. That is exactly the scale at which shipping an unverified guess would do real damage, which is why it stays gated rather than being enabled on the strength of a careful reading.

To enable one, find or derive authoritative vectors, add them to testdata/vectors.tsv, and add the identifier to verified. TestVerifiedMethodsHaveVectors enforces that direction too: nothing can be marked verified unless a vector actually exercises it.

Independent confirmation

Beyond the specification's own vectors, the C1 implementation was checked against a third party IBAN checker for a real ING-DiBa account (DE49500105179144355668). Both report the same four outcomes: correct length, valid bank code, wrong account check digit, correct IBAN checksum.

Extracting the vectors

The vectors in testdata/vectors.tsv were extracted from the specification PDF with pdftotext -layout. One detail is worth recording, because it produced wrong tests before it was caught: test numbers continue across page boundaries, and a naive extractor attributes the numbers at the top of a page to the method that ended on the previous one. Three account numbers were assigned to method 88 that way, and the resulting test failed against a correct implementation. The extractor must stop collecting at page footers.

On this page