This repository has been archived on 2026-02-05. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cvc_checker/checker/scripts/gencard.py
2026-01-06 12:06:12 +08:00

155 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import random
import datetime
import re
class CardGenerator:
def __init__(self):
self.current_year = datetime.datetime.now().year
def luhn_checksum(self, card_number_str):
"""计算 Luhn 校验和"""
digits = [int(d) for d in card_number_str]
checksum = 0
is_second = False
for digit in reversed(digits):
if is_second:
digit *= 2
if digit > 9:
digit -= 9
checksum += digit
is_second = not is_second
return checksum
def calculate_check_digit(self, card_number_without_check):
"""计算最后一位校验位"""
temp_number = card_number_without_check + "0"
checksum = self.luhn_checksum(temp_number)
if checksum % 10 == 0:
return "0"
else:
return str(10 - (checksum % 10))
def generate_card_number(self, pattern):
"""
核心生成逻辑:支持任意位置的 'x'
"""
# 1. 确定卡号长度标准 (Amex 15位其他 16位)
# 如果 pattern 已经很长,就用 pattern 的长度,否则根据卡头判断
target_len = 16
if pattern.startswith(('34', '37')):
target_len = 15
# 2. 补全 pattern 到目标长度 (减去最后一位校验位)
# 如果输入的 pattern 比如是 "547958" (长度6),需要补 x 到 15位 (留一位给校验)
# 如果输入已经包含了 x 且长度足够,则保留原样
working_pattern = pattern.lower()
# 移除可能存在的非数字/x字符
working_pattern = re.sub(r'[^0-9x]', '', working_pattern)
# 自动填充 x
if len(working_pattern) < target_len:
working_pattern += 'x' * (target_len - len(working_pattern))
# 截断到 倒数第二位 (最后一位是校验位)
# 注意:如果用户输入了完整的 16位 pattern 且最后一位不是 x我们会覆盖它
# 因为 Luhn 算法要求最后一位必须是计算出来的。
# 除非用户就是想校验?但在生成逻辑里,我们通常假设最后一位是计算的。
base_pattern = working_pattern[:target_len-1]
generated_prefix = ""
for char in base_pattern:
if char == 'x':
generated_prefix += str(random.randint(0, 9))
else:
generated_prefix += char
# 计算校验位
check_digit = self.calculate_check_digit(generated_prefix)
return generated_prefix + check_digit
def parse_date_cvv(self, card_num, m_req, y_req, c_req):
"""
处理日期和CVV的占位符逻辑
"""
# --- Month ---
if m_req in ['(m)', 'rnd', '', None]:
month = str(random.randint(1, 12)).zfill(2)
else:
month = m_req.strip() # 使用用户指定的静态值,如 '05'
# --- Year ---
if y_req in ['(y)', 'rnd', '', None]:
year = str(self.current_year + random.randint(2, 5))
else:
year = y_req.strip() # 使用用户指定的静态值,如 '2023' 或 '23'
# --- CVV ---
if c_req in ['(cvv)', 'rnd', '', None]:
if card_num.startswith(('34', '37')):
cvv = str(random.randint(1102, 9999))
else:
cvv = str(random.randint(112, 999))
else:
cvv = c_req.strip()
return month, year, cvv
def process_line(self, raw_input, count=1):
"""
智能解析输入字符串并生成
支持格式:
- BIN only: 547958
- Pattern: 460723xxxxxxxxxx
- Complex: 5319719xxx5xxx87
- Full: 434256|11|2022|212
- Templates: 434256|(m)|(y)|(cvv)
"""
# 默认值
parts = raw_input.split('|')
# 提取各个部分,没有的就设为 None交给 parse_date_cvv 处理默认逻辑
pattern_part = parts[0] if len(parts) > 0 else ""
month_part = parts[1] if len(parts) > 1 else None
year_part = parts[2] if len(parts) > 2 else None
cvv_part = parts[3] if len(parts) > 3 else None
results = []
for _ in range(count):
# 1. 生成卡号
card_num = self.generate_card_number(pattern_part)
# 2. 处理附属信息
m, y, c = self.parse_date_cvv(card_num, month_part, year_part, cvv_part)
results.append(f"{card_num}|{m}|{y}|{c}")
return results
# --- 测试与演示 ---
if __name__ == "__main__":
gen = CardGenerator()
# 你列出的所有测试用例
test_cases = [
"547958", # 仅 BIN
"460723xxxxxxxxxx", # 带图案
"5319719xxx5xxx87", # 专业用户 (混合 pattern)
"434256|11|2022|212", # 你自己的固定模式
"559917|11|2022|(cvv)", # 随机 CVV
"434256|(m)|(y)|(cvv)", # 全随机占位符
"434256240669|(m)|(y)|(cvv)", # 短卡号 (没有最后4位) -> 会自动补全
"53673712123xxxxx|05|2023|", # 指定长年份
"53673712123xxxxx|05|23|" # 指定短年份
]
print(f"{'INPUT FORMAT':<35} | {'GENERATED OUTPUT'}")
print("-" * 80)
for case in test_cases:
# 每个案例生成 1 条作为演示
output = gen.process_line(case, count=1)[0]
print(f"{case:<35} -> {output}")