Skip to main content
The International Bank Account Number (IBAN) uses the Mod-97-10 checksum algorithm to validate check digits and ensure data integrity.

Mod-97-10 Algorithm

The algorithm validates that the IBAN check digits produce a remainder of 1 when calculated.

Validation Steps

Step 1: Move the first 4 characters to the end
GB29NWBK60161331926819
→ NWBK60161331926819GB29
Step 2: Replace letters with numbers (A=10, B=11, …, Z=35)
N=23, W=32, B=11, K=20, G=16, B=11

NWBK60161331926819GB29
→ 233211102060161331926819161129
Step 3: Calculate modulo 97
233211102060161331926819161129 mod 97 = 1
Step 4: Validate
  • If remainder = 1: IBAN is valid ✓
  • If remainder ≠ 1: IBAN is invalid ✗

Implementation in Go

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func ValidateIBAN(iban string) bool {
	// Remove spaces and convert to uppercase
	iban = strings.ToUpper(strings.ReplaceAll(iban, " ", ""))

	// Check length
	if len(iban) < 15 || len(iban) > 34 {
		return false
	}

	// Step 1: Move first 4 chars to end
	rearranged := iban[4:] + iban[:4]

	// Step 2: Convert letters to numbers (A=10, B=11, ..., Z=35)
	numericIBAN := ""
	for _, char := range rearranged {
		if char >= 'A' && char <= 'Z' {
			numericIBAN += strconv.Itoa(int(char-'A') + 10)
		} else {
			numericIBAN += string(char)
		}
	}

	// Step 3: Calculate mod 97 efficiently (avoids big.Int)
	remainder := 0
	for _, digit := range numericIBAN {
		remainder = (remainder*10 + int(digit-'0')) % 97
	}

	// Step 4: Valid if remainder equals 1
	return remainder == 1
}

func main() {
	testCases := []struct {
		iban  string
		valid bool
	}{
		{"GB29NWBK60161331926819", true},
		{"DE89370400440532013000", true},
		{"GB00INVALID00000000000", false},
	}

	for _, tc := range testCases {
		result := ValidateIBAN(tc.iban)
		status := "✓"
		if !result {
			status = "✗"
		}
		fmt.Printf("%s %s (expected: %v)\n", status, tc.iban, tc.valid)
	}
}