IBAN Maskeleme: TR IBAN Regex ve Mod-97 Kontrolü
Kısa cevap: Türkiye IBAN'ı "TR" ile başlar ve toplam 26 karakterdir: 2 kontrol hanesi, 5 haneli banka kodu, 1 rezerv hane ve 16 haneli hesap numarası. Metinde boşluklu yazımı da yakalayan bir regex kullanın, mod-97 ile doğrulayın ve yalnızca son dört haneyi bırakarak maskeleyin.
TR IBAN'ın yapısı (26 karakter)
Uluslararası banka hesap numarası (IBAN) ülkeden ülkeye uzunluk değiştirir. Türkiye'de sabit uzunluk 26'dır:
| Parça | Uzunluk | Örnek |
|---|---|---|
| Ülke kodu | 2 | TR |
| Kontrol haneleri | 2 | 33 |
| Banka kodu | 5 | 00061 |
| Rezerv | 1 | 0 |
| Hesap numarası | 16 | 0519786457841326 |
İnsanlar IBAN'ı çoğu zaman dört hanelik gruplar halinde yazar: TR33 0006 1005 1978 6457 8413 26. Bazen küçük harf (tr33…), bazen hiç boşluksuz yazarlar. Maskeleme kodunuz bu üç biçimi de aynı değere indirgemelidir.
IBAN kişisel veri sayılır: belirli bir kişinin veya kurumun hesap bilgisidir. Destek kayıtlarında, fatura PDF'lerinde, e-posta imzalarında ve LLM'e yapıştırılan metinlerde sık görünür. Log'a veya üçüncü taraf modele ham haliyle gitmemelidir.
Regex: boşluklu ve boşluksuz yazım
Önce aday yakalayın, sonra doğrulayın. Tek bir regex ile her şeyi çözmeye çalışmak yerine iki adım daha güvenlidir.
import re
# TR + 24 hane; aralarda isteğe bağlı boşluk
IBAN_ADAY = re.compile(
r"(?<![A-Za-z0-9])TR\s*(?:\d\s*){24}(?!\d)",
re.IGNORECASE,
)
def iban_normalize(s: str) -> str:
return re.sub(r"\s+", "", s).upper()
(?<![A-Za-z0-9]) ve (?!\d) sınırları, daha uzun bir alfanümerik dizinin içinden parça koparmayı azaltır. Yine de yanlış pozitifler olur: rastgele TR + 24 rakam içeren takip kodları. Onları elemek için mod-97 gerekir.
Mod-97 doğrulaması
IBAN standardı (ISO 13616) kontrolü şöyle tanımlar:
- İlk dört karakteri (ülke + kontrol) sona taşı.
- Harfleri sayıya çevir: A=10 … Z=35.
- Elde edilen büyük sayının 97'ye bölümünden kalan 1 olmalı.
def iban_gecerli(s: str) -> bool:
s = iban_normalize(s)
if len(s) != 26 or not s.startswith("TR") or not s[2:].isdigit():
return False
rearranged = s[4:] + s[:4]
digits = "".join(str(int(c, 36)) for c in rearranged)
return int(digits) % 97 == 1
def iban_maskele(metin: str, son: int = 4) -> str:
def replace(m):
raw = m.group()
if not iban_gecerli(raw):
return raw
n = iban_normalize(raw)
# kısmi: ülke + yıldız + son haneler
return n[:2] + ("*" * (24 - son)) + n[-son:]
return IBAN_ADAY.sub(replace, metin)
Örnek (sentetik, yaygın örnek formatı):
Girdi : Ödeme TR33 0006 1005 1978 6457 8413 26 hesabına yapıldı.
Çıktı : Ödeme TR********************1326 hesabına yapıldı.
Gerçek müşteri IBAN'ı test verisi olarak kullanmayın. Mod-97'yi geçen sentetik numaraları kendi üretecinizle üretin.
Python'da int yeterince büyük sayıları tutar. JavaScript'te BigInt kullanın; aksi halde 24+ haneli sayı hassasiyet kaybeder.
Kısmi maskeleme (son 4 hane)
Kısmi maskeleme, çağrı merkezi veya muhasebe ekranında kullanıcının "kendi hesabını tanıması" gerektiğinde işe yarar. LLM isteklerinde ise genellikle etiket daha iyidir:
| Biçim | Örnek | Ne zaman |
|---|---|---|
| Kısmi | TR********************1326 | İnsan ekranı |
| Etiket | [IBAN] | Log, analitik |
| Numaralı etiket | [IBAN_1] | Aynı metinde birden fazla hesap; cevabı geri eşlemek |
Numaralı etiketi kural katmanınız üretir: regex konum verir, siz [IBAN_1] yazarsınız, eşleme tablosu yalnızca sizin tarafınızda kalır. Türkçe PII tespit modeli ise talimatla maskelenmiş metin üretir ([IBAN] gibi); NER span veya offset döndürmez. Geri çevirmek istediğiniz alanlar için kural katmanını kullanın.
TCKN için aynı mantık TCKN maskeleme rehberinde anlatılır.
Loglarda ve yapay zekâ isteklerinde
Maskelemenin yeri, verinin sisteme girdiği ilk noktadır. Sıra şöyle olmalı:
- Metin gelir (form, e-posta, destek kaydı).
- IBAN (ve TCKN, telefon, e-posta) maskelenir.
- Ancak ondan sonra log, arama indeksi veya LLM isteği yazılır.
Tersini yapmak — önce log'a yazıp sonra maskelemek — sızıntıyı yalnızca gizler; ham metin zaten diskte kalmıştır.
Yapay zekâ isteklerinde modelin IBAN'ın kendisine ihtiyacı yoktur. "Ödeme [IBAN_1] hesabına yapıldı" cümlesi, özet veya sınıflandırma için yeterlidir. Cevabı kullanıcıya gösterirken eşleme tablosuyla gerçek numarayı geri koyarsınız.
Kod yazmadan denemek için maskeleme aracı.
Boşluk, OCR ve yaygın yazım tuzakları
Gerçek metinlerde IBAN nadiren "temiz" gelir:
- OCR,
Oile0,Iile1karıştırır - Kullanıcı
TR-33-0006-…gibi tire ekler - Kopyala-yapıştır sırasında satır sonu veya çift boşluk kalır
- Bazı bankalar hesap özetinde IBAN'ı satıra böler
Normalleştirme adımını genişletin: tire ve alt çizgiyi silin, ardından boşlukları kaldırın. OCR şüphesi varsa adayı maskelemeden önce bir insan onayına bırakmak, yanlış maskelemeden iyidir. Sağlamadan geçmeyen adayı zorla maskelemeyin.
def iban_normalize(s: str) -> str:
s = s.upper()
s = re.sub(r"[\-_.]", "", s)
return re.sub(r"\s+", "", s)
Çok satırlı IBAN'lar için önce satır sonlarını boşluğa çevirip tek satırda aramak genelde yeterlidir. Belge ayrıştırıcı (PDF) kullanıyorsanız ham metni birleştirmeden önce sütun sırasını kontrol edin; aksi halde banka kodu ile hesap numarası yer değiştirebilir.
Kural katmanı + model katmanı birlikte
IBAN tek başına maskelense bile aynı cümlede ad soyad, telefon ve e-posta kalabilir. Önerilen sıra:
- Kural katmanı: IBAN, TCKN, telefon, e-posta (konum üretir, geri çevrilebilir)
- Model katmanı: kalan metni talimatla maskele (
[AD], adres vb.) - Log / LLM: yalnızca maskelenmiş metin
Model katmanı PII tespit modelidir: girdiyi yeniden yazar, span listesi vermez. Bu yüzden "IBAN'ı geri koy" ihtiyacı varsa numaralandırmayı kural katmanında bitirin; modele zaten maskelenmiş metni verin veya "IBAN'ları olduğu gibi koru" politikası kullanın.
Ne zaman kısmi, ne zaman etiket?
Muhasebe ekranında son dört hane, kullanıcının hesabı tanımasına yardım eder. Destek özetini bir LLM'e gönderirken son dört hane de gereksizdir; [IBAN_1] yeter. Analitik ve uzun süreli loglarda geri döndürülemez etiket veya tuzlu hash tercih edin. Eşleme tablosunu maskelenmiş metinle aynı yerde saklamayın — bu, maskelemeyi fiilen geri alır.
SSS
Yalnızca regex yeter mi?
Yapısı belli IBAN için regex + mod-97 yeterlidir. Aynı metindeki ad soyad için model katmanı gerekir.
Yabancı IBAN'lar?
Uzunluk ülkeye göre değişir (ör. DE 22, GB 22). Bu rehber TR (26) içindir. Başka ülkeler için uzunluk tablosu ve aynı mod-97 kuralı kullanılır.
Küçük harf tr33… yakalanır mı?
Evet; örnekteki re.IGNORECASE ve iban_normalize küçük harfi büyük harfe çevirir.
Mod-97 geçmeyen bir adayı ne yapmalı?
Olduğu gibi bırakın. Sağlamadan geçmeyen dizi büyük olasılıkla IBAN değildir; maskelemek metni bozar.