Skip to content

Instantly share code, notes, and snippets.

@usr-ein
Last active April 11, 2021 17:28
Show Gist options
  • Save usr-ein/47cf161a84265c75761cb3bcbcd04d50 to your computer and use it in GitHub Desktop.
Save usr-ein/47cf161a84265c75761cb3bcbcd04d50 to your computer and use it in GitHub Desktop.
IBAN Checker and Generator
#!/usr/bin/env python3
"""
Checks for the validity of an IBAN number
You can either pipe IBANS into it, provide it a file directly,
or provide it a single IBAN. In the case of a single IBAN, it'll
show you the steps to verify it.
Samuel Prevost 2021-03-19
"""
import sys
from sys import argv
def main():
"""Main function"""
if len(argv) == 2 and "-h" in argv[1].lower():
print(f"Usage: python {argv[0]} (IBAN | -f iban_list.txt | -f -)")
print("Example:")
print(f"python {argv[0]} FR76 3000 6000 0112 3456 7890 189")
print(f"python {argv[0]} -f iban_list.txt")
print(f"cat iban_list.txt | python {argv[0]}")
exit(1)
if len(argv) == 1 or argv[1] == "-f":
iterator = None
if len(argv) == 1 or (len(argv) == 3 and argv[2] == "-"):
iterator = iter(sys.stdin)
else:
f = open(argv[2], 'r')
iterator = iter(f)
all_good = True
try:
for i, line in enumerate(iterator):
line = line.replace("\n", "")
if len(line) == 0:
continue
if not check_iban(line, verbose=False):
print(f"Line {i+1}: Found invalid IBAN: {line}", file=sys.stderr)
all_good = False
if all_good:
print("All IBAN were valid", file=sys.stderr)
except KeyboardInterrupt:
sys.stdout.flush()
finally:
if hasattr(iterator, "close") and callable(iterator.close):
iterator.close()
else:
iban = ''.join(argv[1:])
if check_iban(iban):
print("Valid IBAN")
else:
print("Invalid IBAN")
exit(1)
print("Done.", file=sys.stderr)
def check_iban(iban, verbose=True):
iban = iban.replace(' ', '').upper()
if verbose: print("IBAN :\t\t\t", iban)
iban = iban[4:] + iban[:4]
if verbose: print("IBAN rearranged: \t", iban)
iban_int = ""
for c in iban:
if ord("A") <= ord(c) <= ord("Z"):
# A=10, B=11, ..., Z=35 that's why letters count double,
# because they're encoded on two decimal digits
iban_int += str(ord(c)-55)
else:
iban_int += c
if verbose: print("IBAN in int: \t\t", iban_int)
iban_int = int(iban_int)
if verbose: print("Mod 97: \t\t", iban_int % 97)
return iban_int % 97 == 1
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Generates valid IBAN numbers that (possibly) don't exist
For now it only works with French (FR) IBAN
To add your country, just find out the length of your
BBAN by counting the number of digits after the first
four chars. Letters in that BBAN part count for two chars.
Samuel Prevost 2021-03-19
"""
from sys import argv
import numpy as np
def main():
"""Main function"""
if len(argv) != 3:
print(f"Usage: python3 {argv[0]} COUNTRY IBAN_COUNT")
exit(1)
# IBAN:
# FR896537193277159353833949
# ^^^^^^^^^^^^^^^^^^^^^^
# Basic Bank Acc Num (BBAN)
bban_sizes = {
"FR": 23
}
country = argv[1]
if country not in bban_sizes.keys():
print("Country not yet supported !")
print("Possible countries:")
print(", ".join(bban_sizes.keys()))
exit(1)
country_code = get_country_code(country)
for _ in range(int(argv[2])):
while True:
try:
r = list(np.random.randint(0, 10, size=bban_sizes[country]))
r += [country_code]
r = int("".join(str(n) for n in r))
check_digits = bruteforce_check_digit(r)
iban_int = add_num(r, check_digits)
iban = to_string_iban(iban_int)
print(iban)
break
except CheckDigitsError:
continue
class CheckDigitsError(ValueError):
pass
def bruteforce_check_digit(r):
for i in range(10, 100):
iban_int = add_num(r, i)
if iban_int % 97 == 1:
return i
raise CheckDigitsError("Didn't find suitable check digit !")
def add_num(a,b):
return int(str(a) + str(b))
def get_country_code(country_letters):
# FR -> 1527
return int("".join([str(ord(c)-55) for c in country_letters]))
def to_string_iban(int_iban):
str_iban = str(int_iban)
str_iban = str_iban[-6:] + str_iban[:-6]
str_iban = chr(int(str_iban[:2])+55) + chr(int(str_iban[2:4])+55) + str_iban[4:]
return str_iban
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment