Skip to content

hamed-zeidabadi/iranian-national-id-validator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🇮🇷 Iranian National ID Validator

اعتبارسنجی کد ملی ایران

npm version npm downloads License: MIT

A comprehensive multi-language implementation of the Iranian National ID (کد ملی) validation algorithm.

یک پیاده‌سازی جامع چند زبانه از الگوریتم اعتبارسنجی کد ملی ایران.

🚀 Quick Start

NPM Package (TypeScript/JavaScript)

npm install iranian-national-id-validator
import { validateIranianNationalId } from 'iranian-national-id-validator';

validateIranianNationalId('0499370899'); // true
validateIranianNationalId('0000000000'); // false

📦 View on NPM | 📖 Full Documentation


📋 Table of Contents


🎯 Introduction

The Iranian National ID (کد ملی) is a unique 10-digit identifier assigned to Iranian citizens. This project provides validation implementations in 7 programming languages, all following the official validation algorithm.

کد ملی ایران یک شناسه یکتای 10 رقمی است که به شهروندان ایرانی اختصاص داده می‌شود. این پروژه پیاده‌سازی اعتبارسنجی را در 7 زبان برنامه‌نویسی ارائه می‌دهد که همگی از الگوریتم رسمی اعتبارسنجی پیروی می‌کنند.

Structure of Iranian National ID

  • Length: Exactly 10 digits
  • Format: Numeric only (0-9)
  • Check Digit: The last digit is a control digit calculated from the first 9 digits
  • Invalid Patterns: IDs with all identical digits (0000000000, 1111111111, etc.) are invalid

🔍 Algorithm Explanation

The validation algorithm consists of three stages:

Stage 1: Format Validation

  • Verify the input is not null/undefined/empty
  • Ensure the input is exactly 10 characters long
  • Confirm all characters are numeric digits (0-9)

Stage 2: Repeated Digit Detection

  • Reject IDs where all 10 digits are identical
  • Invalid patterns: 0000000000, 1111111111, 2222222222, ..., 9999999999

Stage 3: Check Digit Algorithm

The official Iranian National ID algorithm:

  1. Multiply each of the first 9 digits by their position weight:

    • Position 1: weight 10
    • Position 2: weight 9
    • Position 3: weight 8
    • Position 4: weight 7
    • Position 5: weight 6
    • Position 6: weight 5
    • Position 7: weight 4
    • Position 8: weight 3
    • Position 9: weight 2
  2. Calculate the sum of all weighted values

  3. Compute the remainder of the sum divided by 11:

    remainder = sum % 11
    
  4. Validate the check digit (10th digit):

    • If remainder < 2: check digit must equal remainder
    • If remainder >= 2: check digit must equal 11 - remainder

Mathematical Formula

sum = Σ(digit[i] × (10 - i)) for i = 0 to 8
remainder = sum mod 11

valid = {
  checkDigit == remainder,           if remainder < 2
  checkDigit == (11 - remainder),    if remainder >= 2
}

Example Calculation

For National ID: 0499370899

Step 1: Calculate weighted sum
0×10 + 4×9 + 9×8 + 9×7 + 3×6 + 7×5 + 0×4 + 8×3 + 9×2
= 0 + 36 + 72 + 63 + 18 + 35 + 0 + 24 + 18
= 266

Step 2: Calculate remainder
266 % 11 = 2

Step 3: Validate check digit
remainder = 2 (which is >= 2)
Expected check digit = 11 - 2 = 9
Actual check digit = 9
✅ Valid!

🌐 Language Implementations

Language File/Package Type System Key Features
TypeScript/JavaScript npm Static/Dynamic NPM package, dual format (CJS+ESM), 100% coverage
TypeScript typescript/validateIranianNationalId.ts Static Type annotations, modern ES6+
JavaScript javascript/validateIranianNationalId.js Dynamic ES6 modules, arrow functions
Python python/validate_iranian_national_id.py Dynamic Type hints, list comprehension
C# csharp/IranianNationalIdValidator.cs Static .NET 8, LINQ, nullable types
Kotlin kotlin/IranianNationalIdValidator.kt Static Null safety, functional style
Java java/IranianNationalIdValidator.java Static Java 8+ streams
PHP php/IranianNationalIdValidator.php Dynamic PHP 7.4+, strict types

Common Features Across All Implementations

✅ Identical validation logic
✅ Comprehensive inline comments (English & Persian)
✅ Usage examples included
✅ No external dependencies
✅ Pure functions (no side effects)
✅ O(1) time and space complexity


📦 Installation & Usage

🚀 NPM Package (Recommended)

Installation:

npm install iranian-national-id-validator

TypeScript Usage:

import { validateIranianNationalId } from 'iranian-national-id-validator';

const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // true

JavaScript (ES Module) Usage:

import { validateIranianNationalId } from 'iranian-national-id-validator';

const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // true

JavaScript (CommonJS) Usage:

const { validateIranianNationalId } = require('iranian-national-id-validator');

const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // true

Features:

  • ✅ Zero dependencies
  • ✅ TypeScript support with full type definitions
  • ✅ Dual package (CommonJS + ES Module)
  • ✅ Lightweight (< 10KB)
  • ✅ 100% test coverage
  • ✅ Works in Node.js and browsers

Documentation: NPM Package | GitHub


TypeScript (Standalone File)

Installation:

# Copy the file to your project
cp typescript/validateIranianNationalId.ts ./src/

Usage:

import validateIranianNationalId from './validateIranianNationalId';

const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // true

JavaScript (Standalone File)

Installation:

# Copy the file to your project
cp javascript/validateIranianNationalId.js ./src/

Usage:

import validateIranianNationalId from './validateIranianNationalId.js';

const isValid = validateIranianNationalId('0499370899');
console.log(isValid); // true

Python

Installation:

# Copy the file to your project
cp python/validate_iranian_national_id.py ./

Usage:

from validate_iranian_national_id import validate_iranian_national_id

is_valid = validate_iranian_national_id('0499370899')
print(is_valid)  # True

C#

Installation:

# Copy the file to your project
cp csharp/IranianNationalIdValidator.cs ./

Usage:

using IranianNationalIdValidator;

bool isValid = IranianNationalIdValidator.ValidateIranianNationalId("0499370899");
Console.WriteLine(isValid); // True

Kotlin

Installation:

# Copy the file to your project
cp kotlin/IranianNationalIdValidator.kt ./src/main/kotlin/

Usage:

import validateIranianNationalId

fun main() {
    val isValid = validateIranianNationalId("0499370899")
    println(isValid) // true
}

Java

Installation:

# Copy the file to your project
cp java/IranianNationalIdValidator.java ./src/main/java/

Usage:

import IranianNationalIdValidator;

public class Main {
    public static void main(String[] args) {
        boolean isValid = IranianNationalIdValidator.validateIranianNationalId("0499370899");
        System.out.println(isValid); // true
    }
}

PHP

Installation:

# Copy the file to your project
cp php/IranianNationalIdValidator.php ./

Usage:

<?php
require_once 'IranianNationalIdValidator.php';

$isValid = IranianNationalIdValidator::validateIranianNationalId('0499370899');
var_dump($isValid); // bool(true)
?>

🔒 Security & Edge Cases

Input Validation

The validator handles various edge cases:

Input Result Reason
null / undefined / None ❌ False Invalid input
"" (empty string) ❌ False Too short
"123456789" ❌ False Only 9 digits
"12345678901" ❌ False 11 digits (too long)
"123456789a" ❌ False Contains non-numeric
"0000000000" ❌ False All digits identical
"1111111111" ❌ False All digits identical
" 0499370899" ❌ False Contains whitespace
"۰۴۹۹۳۷۰۸۹۹" ❌ False Persian numerals (not ASCII)
"0499370899" ✅ True Valid National ID

Security Considerations

⚠️ Important Limitations:

  1. Format Validation Only: This validator only checks if the ID follows the correct format and algorithm. It does NOT verify if the ID actually exists in government databases.

  2. Not for Authentication: Never use this validator alone for user authentication or identity verification.

  3. Not for Authorization: A valid ID format doesn't grant any permissions or access rights.

  4. Privacy:

    • Never log actual National IDs in production
    • Treat National IDs as sensitive personal information
    • Follow GDPR and local privacy regulations
  5. Input Sanitization:

    • No automatic trimming of whitespace
    • No type coercion (numeric inputs are rejected)
    • No normalization of Persian/Arabic numerals

Performance

  • Time Complexity: O(1) - constant time for all operations
  • Space Complexity: O(1) - no dynamic memory allocation
  • Pure Function: No side effects, thread-safe

Best Practices

DO:

  • Use for client-side validation
  • Use for format checking before database queries
  • Combine with server-side validation
  • Handle validation errors gracefully

DON'T:

  • Use as the sole authentication method
  • Store National IDs in plain text
  • Log National IDs in application logs
  • Trust client-side validation alone

💡 Examples

Valid National IDs

0499370899 ✅
0790419904 ✅
0013542419 ✅

Invalid National IDs

0000000000 ❌ (repeated digits)
1111111111 ❌ (repeated digits)
123456789  ❌ (too short)
12345678901 ❌ (too long)
123456789a ❌ (contains letter)
0499370898 ❌ (wrong check digit)

Integration Example (TypeScript/JavaScript with NPM Package)

import { validateIranianNationalId } from 'iranian-national-id-validator';

// Form validation
function handleSubmit(formData: { nationalId: string }) {
  if (!validateIranianNationalId(formData.nationalId)) {
    throw new Error('Invalid National ID format');
  }
  
  // Proceed with form submission
  submitToServer(formData);
}

// Express.js API endpoint validation
import express from 'express';
const app = express();

app.post('/api/users', (req, res) => {
  const { nationalId } = req.body;
  
  if (!validateIranianNationalId(nationalId)) {
    return res.status(400).json({
      error: 'Invalid National ID format'
    });
  }
  
  // Process valid request
  createUser(req.body);
});

// React form validation
import { useState } from 'react';
import { validateIranianNationalId } from 'iranian-national-id-validator';

function UserForm() {
  const [nationalId, setNationalId] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    
    if (!validateIranianNationalId(nationalId)) {
      setError('کد ملی نامعتبر است');
      return;
    }
    
    // Submit form
    submitForm({ nationalId });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={nationalId}
        onChange={(e) => setNationalId(e.target.value)}
        placeholder="کد ملی"
      />
      {error && <span className="error">{error}</span>}
      <button type="submit">ثبت</button>
    </form>
  );
}

Integration Example (Python)

from validate_iranian_national_id import validate_iranian_national_id

# Django form validation
from django import forms

class UserForm(forms.Form):
    national_id = forms.CharField(max_length=10)
    
    def clean_national_id(self):
        national_id = self.cleaned_data['national_id']
        if not validate_iranian_national_id(national_id):
            raise forms.ValidationError('Invalid National ID format')
        return national_id

# Flask API validation
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/users', methods=['POST'])
def create_user():
    national_id = request.json.get('national_id')
    
    if not validate_iranian_national_id(national_id):
        return jsonify({'error': 'Invalid National ID format'}), 400
    
    # Process valid request
    return jsonify({'success': True})

Integration Example (C#)

using IranianNationalIdValidator;

// ASP.NET Core API validation
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [HttpPost]
    public IActionResult CreateUser([FromBody] UserDto user)
    {
        if (!IranianNationalIdValidator.ValidateIranianNationalId(user.NationalId))
        {
            return BadRequest(new { error = "Invalid National ID format" });
        }
        
        // Process valid request
        return Ok(new { success = true });
    }
}

// Model validation attribute
public class ValidNationalIdAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var nationalId = value as string;
        
        if (string.IsNullOrEmpty(nationalId) || 
            !IranianNationalIdValidator.ValidateIranianNationalId(nationalId))
        {
            return new ValidationResult("Invalid National ID format");
        }
        
        return ValidationResult.Success;
    }
}

// Usage in model
public class UserDto
{
    [ValidNationalId]
    public string NationalId { get; set; }
}

📚 Additional Resources

NPM Package

  • Package: iranian-national-id-validator
  • Repository: GitHub
  • Documentation: Full API documentation and examples available in the package README
  • Bundle Size: < 10KB minified
  • Coverage: 100% test coverage

Quick Links


🤝 Contributing

Contributions are welcome! To add a new language implementation:

  1. Follow the same validation logic
  2. Include comprehensive comments (English & Persian)
  3. Add usage examples
  4. Follow the language's coding conventions
  5. Update this README with the new implementation

For the NPM package, please visit the package repository for contribution guidelines.


📄 License

This project is provided as-is for educational and practical use. Feel free to use it in your projects.


🙏 Acknowledgments

Based on the official Iranian National ID validation algorithm used by Iranian government systems.

الگوریتم رسمی اعتبارسنجی کد ملی ایران که توسط سیستم‌های دولتی ایران استفاده می‌شود.


Made with ❤️ for the Iranian developer community

با ❤️ برای جامعه توسعه‌دهندگان ایرانی ساخته شده است

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages