Menu

Thuật toán Luhn: cách tính chữ số kiểm tra thẻ

Thuật toán Luhn giải thích vì sao chữ số cuối của số thẻ lại đặc biệt. Hướng dẫn cách tính tay, cách kiểm tra và những giới hạn cần biết.

Đăng ngày

  • dữ liệu thử
  • thanh toán
  • kiểm thử

Thuật toán Luhn là phép tính đơn giản đứng sau chữ số cuối cùng của mọi số thẻ, và cũng là lý do vì sao một dãy số bịa vẫn có thể vượt qua bước kiểm tra đầu tiên. Bài này sẽ chỉ cho bạn cách tính tay trong vài phút, cách nhận ra một số đã bị gõ nhầm, và vì sao vượt qua phép kiểm tra này không có nghĩa là tấm thẻ tồn tại.

Vì sao lại cần một chữ số kiểm tra

Con người gõ số thẻ rất nhiều lần mỗi ngày, trên bàn phím máy tính, trên bàn phím số của điện thoại, và trong những dãy số dài mười lăm hay mười sáu chữ số. Sai sót là chuyện bình thường: một ngón tay nhấn lệch, hai chữ số bị đổi chỗ cho nhau, hoặc một chữ số bị bỏ sót khi đọc từ giấy.

Nếu không có cơ chế phát hiện, một lỗi như vậy chỉ lộ ra khi hệ thống đã gửi yêu cầu đi và chờ đợi vài giây để nhận về một thông báo từ chối khó hiểu. Chữ số kiểm tra biến việc đó thành một phép tính tức thời, chạy ngay trên máy của người dùng, và cho ra một câu trả lời rõ ràng: dãy số này không thể là số thẻ hợp lệ.

Phương pháp này do Hans Peter Luhn đề xuất khi ông làm việc tại IBM trong thập niên 1950, và sau đó được đưa vào tiêu chuẩn quốc tế về cấu trúc số thẻ. Điều đáng chú ý là nó ra đời từ rất lâu trước khi thương mại điện tử tồn tại, nhưng vẫn còn nguyên giá trị vì nó rẻ, nhanh và không cần thêm dữ liệu nào ngoài chính dãy số.

Thuật toán Luhn hoạt động như thế nào?

Cũng nằm trong cùng mạch kiểm tra đó, phần dưới đây đi vào cách phép tính này được thực hiện, kèm theo một bảng tính chi tiết để bạn đối chiếu từng bước. Bạn hãy tưởng tượng một dãy số ví dụ gồm mười chữ số, chẳng hạn 4 9 9 2 7 3 9 8 7 1. Quy tắc gồm bốn bước, và bạn có thể làm hoàn toàn bằng tay.

  1. Bắt đầu từ phía bên phải và đếm ngược về bên trái, nhân đôi mọi chữ số nằm ở vị trí thứ hai, thứ tư, thứ sáu và cứ thế.
  2. Với mỗi kết quả nhân đôi mà lớn hơn chín, hãy trừ đi chín. Cách này tương đương với việc cộng hai chữ số của kết quả lại với nhau, nhưng nhanh hơn.
  3. Cộng tất cả các giá trị đã xử lý với những chữ số không bị nhân đôi.
  4. Nếu tổng cuối cùng chia hết cho mười, dãy số vượt qua phép kiểm tra. Nếu không, nó đã bị gõ nhầm ở đâu đó.

Với dãy số ở trên, các chữ số ở vị trí chẵn khi đếm từ phải sang là 7, 9, 7, 9 và 4. Nhân đôi chúng ta được 14, 18, 14, 18 và 8; trừ chín ở những giá trị vượt quá chín, ta còn 5, 9, 5, 9 và 8. Cộng lại với các chữ số còn lại là 1, 8, 3, 2 và 9, tổng thu được là năm mươi mốt. Vì năm mươi mốt không chia hết cho mười, dãy số này không hợp lệ.

Cách trình bày theo bảng giúp bạn nhìn ra ngay chỗ nào sai khi tự kiểm tra một dãy số dài.

Vị trí từ phải sang Chữ số Nhân đôi? Giá trị sau xử lý
1 1 Không 1
2 7 Có 5
3 8 Không 8
4 9 Có 9
5 3 Không 3
6 7 Có 5
7 2 Không 2
8 9 Có 9
9 9 Không 9
10 4 Có 8
Tổng 51

Khi bạn đã quen, việc kiểm tra một số thẻ chỉ mất vài giây, và bạn có thể làm ngay trong đầu với những dãy số ngắn. Với dãy số dài, hãy viết ra giấy theo đúng thứ tự từ phải sang trái để tránh nhầm vị trí, vì đó là lỗi phổ biến nhất khi tính tay.

Chữ số kiểm tra được chọn như thế nào?

Ở phần trên, chúng ta kiểm tra một dãy số đã hoàn chỉnh. Nhưng khi ngân hàng phát hành tạo số thẻ mới, họ làm ngược lại: họ có sẵn phần tiền tố và phần số tài khoản, rồi cần tìm chữ số cuối cùng sao cho tổng chia hết cho mười.

Cách làm rất trực tiếp. Trước hết, hãy tính tổng của tất cả các chữ số theo quy tắc nhân đôi, nhưng tạm coi chữ số cuối cùng là số không. Sau đó lấy phần dư của tổng khi chia cho mười, rồi lấy mười trừ đi phần dư đó. Kết quả chính là chữ số cần điền; nếu phần dư bằng không thì chữ số kiểm tra cũng bằng không.

Đây cũng chính là cách các công cụ sinh số thẻ thử hoạt động: chúng tạo phần thân số theo cấu trúc của mạng thẻ, rồi tính chữ số cuối để dãy số trông hoàn toàn bình thường.

Phép kiểm tra này bắt được lỗi gì và bỏ sót lỗi gì?

Nếu bạn đang cân nhắc xem có nên dựa vào thuật toán Luhn để bảo vệ hệ thống của mình, hãy nhìn vào bảng sau. Điều quan trọng là hiểu rõ ranh giới của nó.

Loại lỗi Bị phát hiện?
Gõ sai một chữ số Luôn luôn
Hai chữ số liền kề bị đổi chỗ Gần như luôn luôn, trừ một vài cặp đặc biệt
Một chữ số bị bỏ sót hoặc thêm vào Thường là có, tùy vị trí
Số thẻ giả được tạo có chủ đích Không bao giờ

Dòng cuối cùng là dòng quan trọng nhất. Bất kỳ ai cũng có thể ngồi tính ra một dãy số vượt qua phép kiểm tra này trong vài phút, kể cả khi họ chưa từng nhìn thấy một tấm thẻ. Vì vậy, trong mọi tài liệu kỹ thuật, thuật toán Luhn được xếp vào nhóm kiểm tra tính toàn vẹn dữ liệu, cùng nhóm với việc kiểm tra độ dài hay định dạng, chứ không phải nhóm biện pháp bảo mật.

Có nên dùng thuật toán Luhn để kiểm tra thẻ không?

Có, nhưng chỉ như một bước lọc sớm. Giá trị lớn nhất của nó là cải thiện trải nghiệm người dùng: thay vì để khách hàng chờ vài giây rồi nhận một thông báo từ chối, bạn phát hiện lỗi gõ ngay lập tức và chỉ cho họ biết chữ số nào có vẻ sai.

Điều bạn không nên làm là dùng nó để quyết định một tấm thẻ có thật hay không, hoặc để chặn một đơn hàng. Hãy để bước xác thực thật do hệ thống thanh toán và ngân hàng phát hành thực hiện. Kiểm tra ở phía máy khách chỉ là một lớp hỗ trợ, không bao giờ là lớp bảo vệ.

Dùng công cụ để kiểm tra nhanh

Nếu bạn cần một dãy số để thử biểu mẫu mà không muốn ngồi tính tay, trình tạo số thẻ tín dụng giả của trang này sẽ sinh ra nhiều số thẻ thử cùng lúc, đúng định dạng và hợp lệ theo phép kiểm tra chữ số. Bạn chỉ cần chọn mạng thẻ, chọn số lượng, rồi sao chép kết quả vào biểu mẫu hoặc vào mã kiểm thử. Nếu bạn muốn tự tay phá một dãy số hợp lệ để xem hệ thống phản ứng ra sao, hãy sửa đúng một chữ số bất kỳ ở giữa dãy và xem thông báo lỗi xuất hiện.

Mọi số thẻ do công cụ tạo ra đều đúng cấu trúc và hợp lệ theo thuật toán Luhn, nhưng chúng chưa từng được phát hành và không thể dùng để thanh toán thật.

Phần dành cho nhà phát triển

Khi lắp phép kiểm tra này vào một luồng xử lý, thứ tự các bước quan trọng hơn bạn tưởng. Một trình tự hợp lý thường là: loại bỏ khoảng trắng và dấu gạch nối, kiểm tra rằng chuỗi chỉ còn toàn chữ số, kiểm tra độ dài nằm trong khoảng hợp lệ, kiểm tra tiền tố có thuộc một mạng thẻ đã biết, và cuối cùng mới tính chữ số kiểm tra. Đặt phép tính Luhn lên trước sẽ khiến bạn phải xử lý những chuỗi chứa chữ cái, và thông báo lỗi trả về sẽ khó hiểu với người dùng.

Vài điều khác đáng lưu ý:

  • Chữ số kiểm tra nằm ở cuối chuỗi, luôn tính từ phía bên phải. Nếu bạn xử lý một chuỗi đã bị cắt bớt hoặc đảo ngược ở đâu đó trong luồng, kết quả sẽ sai một cách âm thầm.
  • Đừng gộp phép kiểm tra chữ số với phép kiểm tra độ dài thành một hàm duy nhất. Khi chúng tách rời, thông báo lỗi mới đủ cụ thể để người dùng sửa đúng chỗ.
  • Trong mã kiểm thử, hãy viết ca cho cả hai chiều: một dãy số hợp lệ phải được chấp nhận, và một dãy số sai chữ số kiểm tra phải bị từ chối. Nếu bạn chỉ kiểm thử chiều thuận, một lỗi đảo điều kiện có thể lọt qua toàn bộ bộ kiểm thử.
  • Cẩn thận với những giá trị đầu vào có độ dài bằng không hoặc chỉ gồm một chữ số. Phép tính vẫn chạy và có thể trả về kết quả dương tính giả nếu bạn không chặn trước.
  • Ghi chú rõ trong mã rằng phép kiểm tra này chỉ phát hiện lỗi gõ. Người đọc sau này rất dễ hiểu nhầm nó là một lớp bảo mật và đặt niềm tin sai chỗ.

Tiếp theo

Nếu bạn muốn hiểu vì sao dãy số thử cần đúng tiền tố của mạng thẻ chứ không chỉ đúng tổng kiểm tra, hãy đọc bài định dạng số thẻ tín dụng. Còn nếu câu hỏi của bạn là làm sao kiểm tra một cách đầy đủ trong ứng dụng, bài cách kiểm tra số thẻ trong mã nguồn sẽ đi vào trình tự các bước và những cái bẫy thường gặp.

Đọc tiếp

Bài viết về Trình tạo số thẻ tín dụng giả