Luhn algoritması, özellikle kredi kartı numaralarının doğrulanmasında yaygın olarak kullanılan bir algoritmadır. Ancak, bu algoritmanın detayları hakkında pek bir bilgim yok. Luhn algoritması tam olarak nedir, nasıl çalışır ve hangi durumlarda kullanılmak daha doğrudur? Üzerinde kullanılan veriler nasıl hazırlanır ve sonuçlar neyi gösterir?
Luhn Algoritması Nedir?
Tanımı
Luhn algoritması, çek-sum (toplam kontrolü) bazlı bir doğrulama algoritmasıdır. 1954 yılında Hans Peter Luhn tarafından geliştirilmiştir. Genellikle kredi kartı numaralarının doğrulanmasında kullanılır, ancak başka sayısal dizilerde de geçerliliği kontrol etmek için kullanılabilir.
Amacı ve Kullanım Alanları
Luhn algoritması, genel olarak hatalı veya yanlış girilen numaraların algılanmasına yardımcı olur. Algoritma, basit bir modül kullanarak, bir sayısal dizinin geçerli olup olmadığını belirler. Kredi kartları dışında, sosyal sigorta numaraları ve banka hesapları gibi diğer numara serilerinin doğrulanmasında da kullanılabilir.
Luhn Algoritması Nasıl Çalışır?
Adım Adım Açıklama
- Sağdan Sola İşleme: Kredi kartı numarası gibi bir sayı dizisini sağdan sola doğru incelemeye başlayın.
- Çift Basamakları İkiyle Çarpma:
- Dizideki her ikinci basamağı (sağdan başlayarak) iki ile çarpın.
- Eğer çarpım 9’dan büyükse, çarpımın basamaklarının toplamını alın (örneğin, 18 için 1 + 8 = 9).
- Toplamı Hesaplama:
- Dizideki bütün sayıları, çarpılanlar da dahil olmak üzere, toplayın.
- Mod 10 İşlemi:
- Toplamı 10’a bölün ve modunu (kalanını) alın.
- Eğer sonuç 0 ise, sayı dizisi geçerli kabul edilir.
def luhn_check(number):
def digits_of(n):
return [int(d) for d in str(n)]
digits = digits_of(number)
odd_digits = digits[-1::-2]
even_digits = digits[-2::-2]
checksum = sum(odd_digits)
for d in even_digits:
checksum += sum(digits_of(d * 2))
return checksum % 10 == 0
Örnek Üzerinde Çalışma
Örnek: Kredi kartı numarası 4539 1488 0343 6467, Luhn algoritmasına göre nasıl doğrulanır?
- Sağdan başlayarak ikinci sıradaki sayılar: 7, 4, 3, 8 (şeklinde sayılır) alınır ve ikiyle çarpılır.
- Eğer bir çarpım 9’dan büyükse basamakları toplanır.
- Tüm sayılar toplanır.
- Toplamın 10’la bölümünden kalan alınır. Eğer kalan 0 ise, numara geçerlidir.
Hangi Durumlarda Kullanılır?
Avantajları
- Hızlı ve Basit: Çek-sum hesaplanması hızlı ve basittir, bu da büyük veri setleri üzerinde uygulanabilirliğini sağlar.
- Belirli Hataları Tespit Etme: Algoritma, basit veri giriş hatalarını, yer değiştirmiş dijitleri veya basamak kaymalarını tespit etme olanağı sağlar.
Dezavantajları ve Uygun Olmadığı Durumlar
- Sadece Temel Hatalar: Luhn algoritması sadece basit hataları tespit eder. Karmaşık sahtekarlık örüntülerine karşı etkili değildir.
- Veri Güvenliği Sağlamaz: Algoritma, yalnızca sayının geçerliliğini doğrular fakat veri güvenliğini sağlamaz. Sahte ancak Luhn-testinden geçen numaralar oluşturulabilir.
Üzerinde Kullanılan Veriler Nasıl Hazırlanır?
Luhn testine tabi tutulacak sayısal diziler genellikle rakam gruplarından oluşmalıdır. Bu diziler, genellikle 16 haneli kredi kartı numaraları gibi sabit uzunlukta olan sayılardır. Bu numaralar hatalardan arındırılmış veya en azından hataların minimize edildiği ve daha önceden belirlenen kurallara uyan diziler olarak hazırlanır.
Sonuçların Gösterdiği
Algoritmanın çıktısı, sayısal dizinin bir veri tabanında kayıtlı olup olmamasına bakılmaksızın yalnızca bu girdinin belirli biçimsel kurallara uygunluğunu gösterir. Yani Luhn testi geçilmiş bir numara, o numaranın mutlaka geçerli bir kredi kartı olduğu anlamına gelmez.
TERİMLER:
Çek-Sum (Checksum): Bir veri grubu üzerinde hata ayıklamak veya doğruluk kontrolü yapmak için kullanılan bir toplam veya bileşik kontrol numarasıdır.
Luhn Algoritması Nedir?
Luhn algoritması, bir dizi sayının (genellikle kredi kartı numaraları) doğruluğunu kontrol etmek için kullanılan basit bir algoritmadır. Hans Peter Luhn tarafından geliştirilmiştir ve genellikle “modulus 10” veya “mod 10” algoritması olarak da bilinir.
Luhn Algoritması Nasıl Hesaplanır?
Adım 1: Son Rakamın Ayrılması
Numaranın son rakamı olan kontrol rakamı (check digit) dışındaki tüm rakamları alın.
Adım 2: Rakamların Konumlarına Göre Çift veya Tek Olması
Numaraları sağdan sola doğru sırayla (kontrol rakamını ihmal ederek) gözden geçirin. Sağdan ikinci, dördüncü vs. sıradaki rakamlar çift konumdadır (1, 3, 5 konumları).
Adım 3: Çift Konumdaki Rakamların İki Katını Alın
Çift konumda olan her rakamı ikiyle çarpın. Eğer bu çarpım 9’dan büyükse, çıkan değerin rakamlarını toplarsınız (örneğin, 14 → 1 + 4 = 5).
Adım 4: Tek Konumdaki Rakamları Toplayın
Tek konumda olan rakamları ve Adım 3’ten elde edilen değerleri toplayın.
Adım 5: Toplamın Modulus 10’u Alın
Elde edilen toplamı 10’a bölün. Eğer sonuç sıfırsa (yani toplam 10’un katıysa), numara geçerlidir.
Örnek Uygulama
Numara: 4539 1488 0343 6467
-
Kontrol rakamı olan son rakamı 7’yi ayırın.
-
Çift konum:
- 6, 4, 3, 0, 8, 4'ü kontrol edin.
-
Çift konumdaki rakamların iki katı:
- 6 \times 2 = 12 → 1 + 2 = 3
- 4 \times 2 = 8
- 3 \times 2 = 6
- 0 \times 2 = 0
- 8 \times 2 = 16 → 1 + 6 = 7
- 4 \times 2 = 8
-
Tek konum:
- 5, 9, 1, 8, 3, 6
-
Topla:
- Çift konum: 3 + 8 + 6 + 0 + 7 + 8 = 32
- Tek konum: 5 + 9 + 1 + 8 + 3 + 6 = 32
- Toplam: 32 + 32 = 64
-
Mod 10:
- 64 \mod 10 = 4 \neq 0 olduğu için numara geçerli değil.
TERİMLER:
Kontrol rakamı (check digit): Bir dizi sayıdaki hataları tespit etmek amacıyla kullanılan son rakam.
Modulus 10 (mod 10): Bir sayının 10’a bölümü sonucunda kalan sayı.
@Uzman Bu konuda detayli bir calisma yapabilirmisin.
Selçuk Bey, memnuniyetle. Aşağıda Luhn algoritmasını hem kuramsal hem de uygulamaya dönük olarak ayrıntılı ele aldım; adımlar, ispat mantığı, hata tespit kapasitesi, doğru/yanlış örnekler ve üretimde kullanılabilecek kodlarla birlikte.
Özet
- Luhn, bir dizi rakamın biçimsel geçerliliğini mod 10 kontrolüyle sınar; özellikle kredi kartı, IMEI vb. numaralarda kullanılır.
- Tüm tek-rakam (single digit) hatalarını ve bitişik rakam yer değiştirmelerinin neredeyse tamamını yakalar; 09↔90 transpozisyonu istisnadır.
- Güvenlik sağlamaz; sadece biçimsel doğrulamadır. Sahte ama Luhn’dan geçen diziler üretilebilir.
- Uygulamada giriş doğrulama, basit tipografik hata yakalama ve kontrol rakamı üretimi için idealdir; kimlik doğrulama/anti-fraud için yeterli değildir.
- Kısa Tanım ve Amaç
- Tanım: Luhn, bir dizideki rakamların ağırlıklı toplamını 10 ’a göre modlayarak 0 kalanı arayan bir kontrol mekanizmasıdır. Geçerliyse S \bmod 10 = 0 olur.
- Amaç: Veri girişindeki tipik hataları (tek rakam hatası, çoğu bitişik transpozisyon) otomatik tespit etmek; kart/PAN gibi numaralarda hızlı biçim kontrolü yapmak.
- Matematiksel Tanım (özlü)
- Diziyi sağdan sola numaralandırın. Sağdan birinci konum i=1.
- Ağırlıklar: w_i=1 (tek konumlar), w_i=2 (çift konumlar).
- f(d)= eğer 2d<10 ise 2d, değilse 2d-9 (yalnızca w_i=2 olduğunda uygulanır; w_i=1 için d).
- Toplam: S=\sum_i g_i(a_i), burada g_i(a_i)=a_i (tek konum) veya f(a_i) (çift konum).
- Geçerlilik koşulu: S \bmod 10 = 0.
- Algoritma Adımları (doğrulama)
- Sağdan sola git.
- Sağdan ikinci, dördüncü, … konumlardaki rakamları ikiyle çarp; sonuç >9 ise 9 çıkar (yani rakamları topla).
- Tüm rakamları topla.
- Toplamın 10 ile bölümünden kalan 0 ise dizi geçerli.
- Kontrol Rakamı Üretimi
- Kontrol rakmı hariç dizinin S toplamını hesapla.
- Ekleyeceğin kontrol rakmı c için (S + c) \bmod 10 = 0 olmalı; yani c = (-S) \bmod 10.
- Örnek ve Hatalı Sonucu Düzeltme
Örnek numara: 4539 1488 0343 6467
Hesap:
- Sağdan çift konumlar: 6, 6, 4, 0, 8, 1, 3, 4
- İkiyle çarp ve 9’dan büyükse 9 çıkar: 12→3, 12→3, 8→8, 0→0, 16→7, 2→2, 6→6, 8→8
- Toplam: 3+3+8+0+7+2+6+8=37
- Sağdan tek konumlar: 7, 4, 3, 3, 8, 4, 9, 5
- Toplam: 7+4+3+3+8+4+9+5=43
- Genel toplam: 37+43=80
- 80 \bmod 10 = 0 olduğundan sayı geçerlidir.
Not: Önceki mesajda bu örnek için 64 toplamıyla “geçersiz” sonucu verilmiş; ara toplama bir rakam hatası karışmış. Doğru toplam 80 ’dir ve dizi geçerlidir.
- Hata Tespit Kapasitesi (ne yakalar, neyi kaçırır)
- Tespit eder:
- Tüm tek-rakam hataları (herhangi bir rakamın farklı bir rakamla değişmesi, S \bmod 10 ’u değiştirir).
- Bitişik rakam transpozisyonlarının neredeyse tamamı.
- Kaçırabildiği özel durum:
- 09↔90 bitişik transpozisyonu. Bunun dışında bitişik transpozisyonları büyük oranda yakalar.
- Yakalamaz:
- Sistematik veya kasıtlı kalıplar, birden fazla hatanın belirli kombinasyonları, rastgele oluşturulmuş fakat Luhn’u geçen sahte diziler.
- Kullanım Alanları (ne zaman uygundur)
- Kredi/banka kartı PAN doğrulaması (ISO/IEC 7812 ailesi).
- IMEI gibi cihaz kimlikleri.
- Abone/üye numaraları, sipariş/etiket kodları gibi kullanıcı girişli sayısal dizilerde basit hata yakalama.
- Form doğrulama ve kontrol rakmı ekleme.
- Uygun Olmayan Durumlar ve Sınırlamalar
- Güvenlik/anti-fraud için yeterli değildir; yalnızca biçim kontrolüdür.
- Varlık/doğruluk teyidi yapmaz (bankada gerçekten kayıtlı mı, limit var mı vb.).
- Alfasayısal kodlarda doğrudan kullanılamaz; bunun için Luhn mod N türleri veya alternatifler (Verhoeff, Damm) gerekir.
- Veri Hazırlama ve Uygulama İpuçları
- Normalize edin: Boşluk, tire gibi tüm rakam dışı karakterleri temizleyin; lider sıfırları koruyun.
- Uzunluk kontrolü: Kart için yaygın uzunluklar 13–19; ağ/ülkeye göre değişebilir.
- Hataları kullanıcı dostu bildirin: “Numara biçimsel olarak geçersiz görünüyor.”
- Güvenlik/uyum:
- PAN gibi hassas veriler PII’dir. PCI DSS’e uyun; tam PAN’ı saklamayın, maskeleyin/tokene edin.
- Loglarda tam numara bulundurmayın; son 4 haneyle maskeleyin.
- Kod Örnekleri
A) Python 3.8+ (doğrulama ve kontrol rakmı üretimi)
Açıklama: Girdi dizge olmalı; rakam dışını temizler. Çok uzun dizilerde de çalışır.
# Python 3.8+
import re
def luhn_clean(s: str) -> str:
"""Keep digits only."""
return re.sub(r"\D", "", s or "")
def luhn_checksum(num_str: str) -> int:
"""
Return the Luhn checksum (sum % 10) for a numeric string.
"""
digits = [int(ch) for ch in num_str]
total = 0
# Process from right to left
parity = len(digits) % 2 # if len is even, we double even indices (0-based)
for i, d in enumerate(digits):
if i % 2 == parity:
# Double and subtract 9 if > 9
dd = d * 2
if dd > 9:
dd -= 9
total += dd
else:
total += d
return total % 10
def luhn_is_valid(s: str) -> bool:
"""
Validate a full number (including check digit).
"""
ns = luhn_clean(s)
if not ns:
return False
return luhn_checksum(ns) == 0
def luhn_check_digit(s_without_check: str) -> int:
"""
Compute the check digit for a number without the check digit.
"""
base = luhn_clean(s_without_check)
if not base:
raise ValueError("Empty base number")
# Append a zero as placeholder and compute what makes it % 10 == 0
partial = base + "0"
c = luhn_checksum(partial)
return (10 - c) % 10
def luhn_append_check_digit(s_without_check: str) -> str:
"""
Return the full number with the computed check digit appended.
"""
d = luhn_check_digit(s_without_check)
return luhn_clean(s_without_check) + str(d)
# Examples / expected outputs:
assert luhn_is_valid("4539 1488 0343 6467") is True
assert luhn_is_valid("4111-1111-1111-1111") is True
assert luhn_is_valid("49927398716") is True
assert luhn_is_valid("49927398717") is False
# Generating a check digit:
assert luhn_append_check_digit("7992739871") == "79927398713"
Beklenen çıktı:
- 4539 1488 0343 6467 → True
- 4111-1111-1111-1111 → True
- 49927398716 → True
- 49927398717 → False
- 7992739871 + check → 79927398713
B) JavaScript (tarayıcı/Node, form doğrulama için)
Açıklama: Rakam dışını temizler; hem doğrular hem kontrol rakmı üretir.
// JS (ES6+)
function cleanDigits(s) {
return (s || "").replace(/\D/g, "");
}
function luhnChecksum(numStr) {
const digits = numStr.split("").map((c) => parseInt(c, 10));
let sum = 0;
let doubleNext = false; // start from rightmost
for (let i = digits.length - 1; i >= 0; i--) {
let d = digits[i];
if (doubleNext) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
doubleNext = !doubleNext;
}
return sum % 10;
}
function luhnIsValid(s) {
const ns = cleanDigits(s);
if (!ns) return false;
return luhnChecksum(ns) === 0;
}
function luhnCheckDigit(base) {
const ns = cleanDigits(base);
if (!ns) throw new Error("Empty base number");
const c = luhnChecksum(ns + "0");
return (10 - c) % 10;
}
function luhnAppendCheckDigit(base) {
const ns = cleanDigits(base);
return ns + luhnCheckDigit(ns);
}
// Quick tests
console.log(luhnIsValid("4539 1488 0343 6467")); // true
console.log(luhnAppendCheckDigit("7992739871")); // "79927398713"
C) PostgreSQL 13+ (CHECK constraint için)
Açıklama: Metin kolondan rakamları temizleyip Luhn doğrulayan fonksiyon ve kısıt.
-- Create a function to validate Luhn
CREATE OR REPLACE FUNCTION luhn_is_valid(text) RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
WITH cleaned AS (
SELECT regexp_replace($1, '\D', '', 'g') AS ns
),
rev AS (
SELECT reverse(ns) AS r FROM cleaned
),
idx AS (
SELECT generate_series(1, length(r)) AS i, r
FROM rev
),
calc AS (
SELECT
SUM(
CASE
WHEN i % 2 = 0 THEN -- even position from right -> doubled
CASE
WHEN (substr(r, i, 1))::int * 2 > 9
THEN (substr(r, i, 1))::int * 2 - 9
ELSE (substr(r, i, 1))::int * 2
END
ELSE (substr(r, i, 1))::int
END
) AS total
FROM idx
)
SELECT (total % 10) = 0 FROM calc;
$$;
-- Example table with constraint
CREATE TABLE cards (
id serial PRIMARY KEY,
pan text NOT NULL,
CONSTRAINT pan_luhn_valid CHECK (luhn_is_valid(pan))
);
- Performans, Doğruluk ve Bakım
- Zaman karmaşıklığı: O(n), tek geçiş.
- Bellek: O(1).
- Testler: Aykırı durumlar (boş giriş, çok kısa dizi, sadece boşluk/ayraç, lider sıfırlı sayılar) için birim testleri ekleyin.
- Yerelleştirme: Hata mesajlarını son kullanıcı diliyle verin; maskeleme (örn. **** **** **** 6467) kullanın.
- Örnek Test Numaraları (yalnızca test/öğrenme amaçlı)
- Visa: 4111 1111 1111 1111 (geçerli, Luhn’u geçer)
- Visa: 4539 1488 0343 6467 (geçerli, Luhn’u geçer)
- Genel örnek: 49927398716 (geçerli), 49927398717 (geçersiz)
Not: Bunlar ağların yaydığı test numaralarıdır; gerçek ödeme yapılmaz.
- Alternatifler ve Varyantlar
- Verhoeff: Transpozisyon hatalarını daha güçlü yakalar; hesaplama biraz daha maliyetlidir.
- Damm: Güçlü hata tespiti; tablo tabanlı yaklaşım.
- Luhn mod N: Alfasayısal diziler için genişletme (örn. 0–9+A–Z gibi).
Kaynaklar ve doğrulama
- ISO/IEC 7812 (kart numaralarıyla ilişkili standart ailesi): Resmi standart özetleri ve açıklamaları için ulusal standart kurumları veya ISO kataloğu.
- Luhn algorithm genel açıklama: Wikipedia, Luhn algorithm (erişim: 22 Eylül 2025, Europe/Brussels).
- PCI DSS Quick Reference: PCI Security Standards Council (erişim: 22 Eylül 2025, Europe/Brussels).
Terimler ve Açıklamalar
- BIN/IIN (Banka Tanımlayıcı Numarası/Issuer Identification Number): Kart numarasının ilk 6–8 hanesi, kartı çıkaran kuruluşu tanımlar. Örn. 411111… Visa ağını işaret edebilir.
- Çek-sum (Checksum): Veri üzerinde hata tespitine yardımcı olan özet türü. Luhn’da toplamın 10 ’a göre kalanı kullanılır.
- IMEI (International Mobile Equipment Identity): Mobil cihaz kimliği; Luhn kontrol rakmı içerir. Cihaz envanteri ve kara listelemelerde önemlidir.
- ISO/IEC 7812: Kart numaralandırma için uluslararası standart. PAN yapısı, IIN/BIN vb. tanımlar.
- Kontrol rakamı (Check digit): Bir dizinin sonuna eklenen, Luhn toplamını 0 \bmod 10 yapacak rakam. Veri giriş hatalarını yakalamayı sağlar.
- Luhn mod N: Luhn’un alfasayısal karakter kümelerine genişletilmiş sürümü. Hediye kartı/kupon kodları gibi alanlarda kullanılabilir.
- Mod (Modulus): Bir sayının bölüme göre kalanı. Luhn’da S \bmod 10 hesaplanır.
- PAN (Primary Account Number): Kart üzerindeki 13–19 haneli birincil hesap numarası. Luhn kontrolü içerir.
- PCI DSS (Payment Card Industry Data Security Standard): Kart verisi güvenliği için endüstri standardı. Uygulamalar için depolama/maskeleme/günlükleme kuralları belirler.
- Tokenizasyon: Hassas veriyi temsil eden geri döndürülebilir/geri döndürülemez belirteçlerle değiştirme. Sızıntı riskini azaltır.
- Verhoeff algoritması: Daha güçlü transpozisyon tespiti sağlayan alternatif kontrol rakmı algoritması. Kimlik/seri numaralarında tercih edilebilir.
- Yer değiştirme hatası (Transposition error): İki bitişik rakamın yer değiştirmesi. Luhn bunların çoğunu yakalar; 09↔90 istisnadır.
İsterseniz, mevcut forum başlığındaki ilk gönderiyi düzenleyerek doğru örnek hesaplamayı ve burada paylaştığım kod parçalarını ekleyebilirim; ayrıca dilerseniz bir mini kütüphane/utility hazırlayıp GitHub’a da koyarım.