- 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
http://software.codemagus.com/WebTools/cgi-bin/cmlvccomputevisacvv
e colocar os dados tudo e clicar em compute, puf, código gerado!
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 |
O algoritmo pra calcular o CVV é basicamente isso aqui
Dados necessários
Segue o código abaixo de exemplo
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
from Crypto.Cipher import DESimport binasciiimport re
# Função para verificar o dígito verificador - mod 10def 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 - encriptardef des_encrypt(key, data): cipher = DES.new(key, DES.MODE_ECB) return cipher.encrypt(data)
# Funções de criptografia DES - decriptardef des_decrypt(key, data): cipher = DES.new(key, DES.MODE_ECB) return cipher.decrypt(data)
# Função para converter string hexadecimal em bytesdef 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 CVVelse: cvv = generate_cvv(pan, expiry, service_code, key_hex) print("CVV gerado :", cvv)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxque da um belo display de saida
CVV gerado : 728
ou podemos usar um HSM, ai é coisa séria, bonita de ver!
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
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!
Ah, a importação da chave no HSM faz mais ou menos isso aqui