Pesquisar este blog

Mostrando postagens com marcador código de segurança cartão. Mostrar todas as postagens
Mostrando postagens com marcador código de segurança cartão. Mostrar todas as postagens

quinta-feira, 29 de maio de 2025

Como gerar CVV/CVC - código de segurança cartão de crédito - moleza moleza

Bom vamos direto ao ponto... vou tentar achar a documentação sobre o algoritmo certinho, lembro de já ter lido alguma vez em algum manual da VISA que acabamos copiando pro ELO, na AMEX eu lembro bem, mas é outro esquema diferente da Visa e da Mastercard.


Basicamente precisa do:
-  CARTAO, vulgo PAN
- Vencimento 
e das chaves de criptografia 
o código de segurança varia de acordo com o que vamos calcular, mas bora deixar fixo em 999 que acho era o valor pra quando formos calcular o que fica atrás do cartao, o CVV2/CVC2/CVE2.

Vamos usar esses dados aqui

5067240000000019 --> confere pra ver se é 9 mesmo o digito verificador!
2512

CVK A - (em claro) - 0123456789012345
CVK B - (em claro) - ABCDEF0123456789

Beleza, nao precisamos de mais nada, só isso já basta

Agora é pra quem é virjão de tudo, pode ir nesse site aqui

http://software.codemagus.com/WebTools/cgi-bin/cmlvccomputevisacvv

e colocar os dados tudo e clicar em compute, puf, código gerado!

Figura 1 - Screen Shot site Code Magus


ou pode ser aqui
https://paymentcardtools.com/card-security-values/cvv-calculator
Figura 2 - Print Screen geracao do CVC pelo paymentcardtools.com


esse até mais legal que mostra até um KCV - key check value de cada chave! e valida o numero do cartao!


temos ainda outras opções, como o
https://fint-1227.appspot.com/cvvcalc/

Figura 3 - Geracao de código de segurança pelo site https://fint-1227.appspot.com/


Mas voce é curioso e quer saber como as coisas funcionam, fazer um código, um programa! Mas antes disso, vamos executar o calculo usando um grande companheiro, o BPTools

Figura 4 - Geracao do CVV usando o BPTools - módulo de Calculadora Criptografica


Mas poderiamos tambem gerar isso na mão, usando o 3DES aplicado igual mandam no figurino, só lembrando que o Triple DES nao é nada mais nada menos que o DES usado 3 vezes!!! 

Criptografa com a chave 1 -> Descriptografa com a chave 2 -> Criptografa com a chave 1


O algoritmo pra calcular o CVV é basicamente isso aqui

Dados necessários
- Chave em claro (2 componentes)
- Cartao
- Vencimento
- Código de serviço


Preparação dos Dados -> DATA
Combine os dados: Concatene o Número do Cartão (PAN), a data de validade e o código de serviço.
Complete com zeros: Adicione zeros à direita dessa sequência até que ela tenha 32 caracteres no total.

Processo de Criptografia 
Com a "DATA" preparada, o processo de criptografia e descriptografia é o seguinte:

- Criptografe a primeira metade da "DATA" (parte da esquerda) usando a primeira metade da chave, bom deixar claro, parte da esquerda é a primeira! (é uma operação DES) .
- Aplique uma operação XOR no resultado com a segunda metade da "DATA".
==> aqui é o tal do Triple DES (3DES)
- Criptografe novamente o resultado utilizando a primeira metade da chave (DES).
- Descriptografe o resultado com a segunda metade da chave (DES).
- Criptografe mais uma vez o valor obtido, usando a primeira metade da chave (DES).

Geração do CVV
Extraia apenas os dígitos da ultima operacao de DES, os primeiros três números correspondem ao CVV.




Segue o código abaixo de exemplo
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

from Crypto.Cipher import DES
import binascii
import re

# Função para verificar o dígito verificador - mod 10
def luhn_check(card_number):
    digits = [int(d) for d in card_number]
    checksum = 0
    parity = len(digits) % 2
    for i, d in enumerate(digits):
        if i % 2 == parity:
            d *= 2
            if d > 9:
                d -= 9
        checksum += d
    return checksum % 10 == 0

# Função para preencher à direita com zeros      
def pad_right(s, length, pad_char='0'):
    return s.ljust(length, pad_char)


# Funções de criptografia DES - encriptar
def des_encrypt(key, data):
    cipher = DES.new(key, DES.MODE_ECB)
    return cipher.encrypt(data)

# Funções de criptografia DES - decriptar
def des_decrypt(key, data):
    cipher = DES.new(key, DES.MODE_ECB)
    return cipher.decrypt(data)

# Função para converter string hexadecimal em bytes
def hexstr_to_bytes(hexstr):
    return binascii.unhexlify(hexstr)

# Função para gerar o código de segurança!
# CVV (Card Verification Value) CVC (Card Verification Code) CVE (Código de Verificacao ELO)

def generate_cvv(pan, expiry, service_code, key_hex):
    # Quebra a chave em duas partes ("chave a e chave b") com 16 caracteres cada
    key_a = hexstr_to_bytes(key_hex[:16])
    key_b = hexstr_to_bytes(key_hex[16:32])

    # Concatena Cartao, vencimento (AAMM) e código de serviço
    data = pan + expiry + service_code
    # "pad" com zeros até 32 caracteres
    data = pad_right(data, 32, '0')  
   
    # Quebra em duas metades left e right halves com 16 caracteres cada
    left = data[:16]
    right = data[16:]
   
    # Converte para hexadecimal
    left_bytes = binascii.unhexlify(left)
    right_bytes = binascii.unhexlify(right)
   
    # Criptografa a parte da esqueda com a "chave_a"
    encrypted_left = des_encrypt(key_a, left_bytes)

    # Faz XOR com o resultado com a parte direita
    xor_result = bytes([a ^ b for a, b in zip(encrypted_left, right_bytes)])
   
    # Criptografa com a "chave a"
    TDES_passo1 = des_encrypt(key_a, xor_result)
   
    # Decriptografa com a "chave b"
    TDES_passo2 = des_decrypt(key_b, TDES_passo1)

    # Criptografa novamente com a "chave a"
    TDES_passo3 = des_encrypt(key_a, TDES_passo2)

    # Pega apenas os dígitos do resultado, afinal estavamos trabalhando com hexadecimal
    digits = re.sub(r'\D', '', TDES_passo3.hex())

    # e queremos os primeiros 3 dígitos que é nosso CVV
    return digits[:3]  

# Nossos dados de entrada #
key_hex = "0123456789012345ABCDEF0123456789"
pan = "5067240000000019"
expiry = "2512"      
service_code = "999"  

# Validações dos dados de entrada #
if not luhn_check(pan):
    raise ValueError("Número do cartão inválido (verifique o dígito verificador).")
if len(pan) != 16 or not pan.isdigit():
    raise ValueError("O PAN deve ter 16 dígitos numéricos.")
if len(expiry) != 4 or not expiry.isdigit():
    raise ValueError("A data de validade deve ter 4 dígitos numéricos (YYMM).")
if len(service_code) != 3 or not service_code.isdigit():
    raise ValueError("O código de serviço deve ter 3 dígitos numéricos.")
if len(key_hex) != 32 or not all(c in '0123456789ABCDEF' for c in key_hex.upper()):
    raise ValueError("A chave deve ter 32 caracteres hexadecimais (16 bytes).")
if not key_hex.isalnum():
    raise ValueError("A chave deve conter apenas caracteres alfanuméricos (hexadecimais).")
if not key_hex.isupper():
    raise ValueError("A chave deve estar em letras maiúsculas (hexadecimais).")
# Se todos os dados de entrada forem válidos, gera o CVV
else:
    cvv = generate_cvv(pan, expiry, service_code, key_hex)
    print("CVV gerado :", cvv)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

que da um belo display de saida 

CVV gerado : 728


ou podemos usar um HSM, ai é coisa séria, bonita de ver!

Digamos que voce vá usar o Thales Payshield 9000 (que ja ta fora de linha e acho que é bem bom pra ilustrar os comandos e mesmo ser simulado), bom, nao vou dar aula de chaves aqui, mas a de CVV é do esquema U, e do tipo 402, variante 4 e o setimo par de chaves de LMK, que sao {"E0E0010101010101", "F1F1010101010101"} e  usando novamente nosso amigo BP-TOOLS, vai dar isso aqui!

UC68879EF8F0E22A2B8A51FE73409DC16

na real nao estou importando, o comando seria o A4, se nao me engano!

Figura 5 - "Importação da Chave" no HSM


Poderia "importar" de verdade ou usar um outro simulador, igual esse aqui em go, por exemplo

root@Tecladinho:/mnt/c/Windows/System32/go_hsm/bin#
./go_hsm keys import --key 0123456789012345ABCDEF0123456789 --type 402 --scheme U
Key Type: Name: CVK/CSCK, Code: 402, LMKPairIndex: 7, VariantID: 4
Key Scheme: U
Encrypted Key: UC68879EF8F0E22A2B8A51FE73409DC16
KCV: 7FFC84
root@Tecladinho:/mnt/c/Windows/System32/go_hsm/bin#    

que gera a mesma coisa, bom sinal!


Agora usando o comando CW do HSM pra verificar se o valor que a gente ta calculando ta correto!

Figura 6 - Execucao do comando CW pelo BPTools


mas nao to ligado num HSM de verdade, é um Thales Payshield HSM Simulator!

Figura 7 - Thales Simulator

e olha ai, 728! Grande numero!


é isso, grandes lembranças!

Ah, a importação da chave no HSM faz mais ou menos isso aqui

#!/usr/bin/env python3
"""
HSM Thales PayShield - Cálculo de Chave Criptografada

Este script simula o processo de criptografia de uma chave (ex: CVK/CSCK)
sob LMK, seguindo o padrão do HSM Thales PayShield, incluindo aplicação de variants
e cálculo de Key Check Value (KCV).

Ideal para estudos, troubleshooting e validação de processos de importação de chaves.
"""

from Crypto.Cipher import DES3
import binascii

def hex_to_bytes(hex_str):
    """Converte uma string hexadecimal para bytes."""
    return binascii.unhexlify(hex_str)

def bytes_to_hex(data):
    """Converte bytes para uma string hexadecimal maiúscula."""
    return binascii.hexlify(data).decode().upper()

def apply_key_type_variant(lmk_left, lmk_right, variant_id):
    """
    Aplica o variant_id no primeiro byte do LMK LEFT.
    Exemplo: Variant 4 = 0xDE (usado para CVK/CSCK).
    Retorna LMK LEFT modificado e LMK RIGHT inalterado.
    """
    variant_map = {
        0: 0x00,  # Sem variant
        1: 0xA6,
        2: 0x5A,
        3: 0x6A,
        4: 0xDE,  # Usado para CVK/CSCK
        5: 0x2B,
        6: 0x50,
        7: 0x74,
        8: 0x9C,
        9: 0xFA,
    }
   
    if variant_id == 0:
        return lmk_left[:], lmk_right[:]  # Sem alteração
   
    variant_value = variant_map.get(variant_id, 0x00)
   
    # Aplica XOR no primeiro byte do LMK LEFT
    modified_left = bytearray(lmk_left)
    modified_left[0] ^= variant_value
   
    return bytes(modified_left), lmk_right[:]

def encrypt_under_variant_lmk(input_key, lmk_left, lmk_right, scheme_tag):
    """
    Criptografa a chave de entrada sob LMK modificado, usando o esquema 'U' (double-length).
    Para cada metade da chave, aplica um variant diferente no LMK RIGHT.
    """
    if scheme_tag == 'U':
        if len(input_key) != 16:
            raise ValueError("Double-length key necessária para o scheme U")
        scheme_variants = [0xA6, 0x5A]  # Variants padrão do scheme U
    else:
        raise ValueError(f"Unknown scheme tag: {scheme_tag}")
   
    encrypted = bytearray()
   
    for i, scheme_variant in enumerate(scheme_variants):
        # Monta LMK para este segmento (LEFT + RIGHT)
        variant_lmk = bytearray(16)
        variant_lmk[:8] = lmk_left
        variant_lmk[8:16] = lmk_right
       
        # Aplica o variant no primeiro byte do LMK RIGHT
        variant_lmk[8] ^= scheme_variant
       
        # Cria chave 3DES (K1-K2-K1)
        triple_des_key = bytes(variant_lmk) + bytes(variant_lmk[:8])
       
        # Criptografa 8 bytes do segmento da chave
        cipher = DES3.new(triple_des_key, DES3.MODE_ECB)
        segment = input_key[i*8:(i+1)*8]
        encrypted_segment = cipher.encrypt(segment)
        encrypted.extend(encrypted_segment)
   
    return bytes(encrypted)

def calculate_thales_payshield_key():
    """
    Simula o cálculo da chave criptografada sob LMK, conforme o HSM Thales PayShield.
    Mostra passo a passo do processo, incluindo aplicação de variants e análise detalhada.
    """
    print("=== CÁLCULO THALES PAYSHIELD ===\n")
   
    # 1. Dados de entrada (exemplo de CVK double-length)
    clear_key = "0123456789012345ABCDEF0123456789"
    key_type_code = "402"  # CVK/CSCK
    scheme_tag = 'U'       # Esquema double-length
   
    print(f"Chave original: {clear_key}")
    print(f"Key Type: {key_type_code} (CVK/CSCK)")
    print(f"Scheme: {scheme_tag}")
   
    # 2. Detalhes do tipo de chave (exemplo baseado em tabela Go)
    # "402": {Name: "CVK/CSCK", Code: "402", LMKPair: 7, VariantID: 4}
    lmk_pair_index = 7    # LMK 14-15
    variant_id = 4        # Variant 4 = 0xDE
   
    print(f"LMK Pair Index: {lmk_pair_index} (LMK 14-15)")
    print(f"Variant ID: {variant_id}")
   
    # 3. LMKs originais (exemplo)
    lmk_14 = "E0E0010101010101"
    lmk_15 = "F1F1010101010101"
   
    print(f"\nLMK 14 (original): {lmk_14}")
    print(f"LMK 15 (original): {lmk_15}")
   
    lmk_14_bytes = hex_to_bytes(lmk_14)
    lmk_15_bytes = hex_to_bytes(lmk_15)
   
    # 4. Aplica o variant do tipo de chave no LMK LEFT
    modified_lmk_14, modified_lmk_15 = apply_key_type_variant(
        lmk_14_bytes, lmk_15_bytes, variant_id
    )
   
    print(f"\nApós aplicar Variant {variant_id} (0xDE):")
    print(f"LMK 14 modificado: {bytes_to_hex(modified_lmk_14)}")
    print(f"LMK 15 (inalterado): {bytes_to_hex(modified_lmk_15)}")
   
    # Verificação do XOR aplicado
    print(f"Verificação: 0xE0 XOR 0xDE = 0x{0xE0 ^ 0xDE:02X}")
   
    # 5. Prepara a chave de entrada (em bytes)
    input_key_bytes = hex_to_bytes(clear_key)
   
    print(f"\nChave de entrada ({len(input_key_bytes)} bytes): {bytes_to_hex(input_key_bytes)}")
   
    # 6. Criptografa a chave sob LMK modificado, usando o scheme U
    encrypted_key = encrypt_under_variant_lmk(
        input_key_bytes,
        modified_lmk_14,
        modified_lmk_15,
        scheme_tag
    )
   
    print(f"\n=== PROCESSO DE ENCRIPTAÇÃO ===")
    print(f"Scheme '{scheme_tag}' usa variants: [0xA6, 0x5A]")
    print(f"Cada variant encripta 8 bytes da chave")
   
    # 7. Monta resultado final (scheme tag + chave criptografada)
    result = scheme_tag + bytes_to_hex(encrypted_key)

    # 8. Análise detalhada dos segmentos
    print(f"\n=== ANÁLISE DETALHADA ===")
    cvk_a = clear_key[:16]
    cvk_b = clear_key[16:]
    encrypted_a = bytes_to_hex(encrypted_key[:8])
    encrypted_b = bytes_to_hex(encrypted_key[8:16])
   
    print(f"CVK A: {cvk_a} -> {encrypted_a}")
    print(f"CVK B: {cvk_b} -> {encrypted_b}")
   
    # 9. Mostra os LMKs usados para cada segmento (com variants)
    print(f"\n=== VARIANTS DE SCHEME ===")
    base_lmk = modified_lmk_14 + modified_lmk_15
   
    # Para primeiro segmento (variant 0xA6)
    variant_1 = bytearray(base_lmk)
    variant_1[8] ^= 0xA6
    print(f"LMK para CVK A (variant 0xA6): {bytes_to_hex(variant_1)}")
   
    # Para segundo segmento (variant 0x5A)
    variant_2 = bytearray(base_lmk)
    variant_2[8] ^= 0x5A
    print(f"LMK para CVK B (variant 0x5A): {bytes_to_hex(variant_2)}")
   
    return result

def calculate_kcv(key_hex):
    """
    Calcula o Key Check Value (KCV) de uma chave.
    O KCV é obtido criptografando 8 bytes zero com a chave e pegando os 6 primeiros hex.
    """
    key_bytes = hex_to_bytes(key_hex)
    zeros = b'\x00' * 8
   
    if len(key_bytes) == 16:
        # Double-length key - usa 3DES (K1-K2-K1)
        triple_key = key_bytes + key_bytes[:8]
        cipher = DES3.new(triple_key, DES3.MODE_ECB)
    else:
        cipher = DES3.new(key_bytes, DES3.MODE_ECB)
   
    encrypted = cipher.encrypt(zeros)
    return bytes_to_hex(encrypted)[:6]

if __name__ == "__main__":
    # Executa o cálculo principal e mostra resultados
    result = calculate_thales_payshield_key()
   
    print(f"\n=== RESULTADO FINAL ===")
    print(f"Chave criptografada: {result}")
    print(f"Esperado:           UC68879EF8F0E22A2B8A51FE73409DC16")
    print(f"Match? {result == 'UC68879EF8F0E22A2B8A51FE73409DC16'}")
   
    # Calcula e mostra o KCV da chave original
    original_key = "0123456789012345ABCDEF0123456789"
    kcv = calculate_kcv(original_key)
    print(f"\n=== KEY CHECK VALUE ===")
    print(f"KCV calculado: {kcv}")
    print(f"KCV esperado:  7FFC84")
    print(f"KCV Match? {kcv == '7FFC84'}")