Post Técnico
Como Descriptografar Dados de Cartão de Crédito, Parte II
Os clientes frequentemente perguntam: Como posso descriptografar os dados gerados pelo meu leitor de cartão de crédito ID TECH?
A resposta: É necessário conhecer o algoritmo utilizado para criptografar os dados e a chave que foi usada. Com essas informações, é possível descriptografar os dados por meio da chave.
Atualmente, praticamente todos os dados de cartão de crédito são criptografados com uma chave de uso único, obtida por meio de um esquema especial de gerenciamento de chaves chamado DUKPT (sigla para Derived Unique Key Per Transaction, ou seja, Chave Única Derivada por Transação). É fundamental compreender que, no universo DUKPT, cada transação possui sua própria chave. Essa chave não pode ser reutilizada em nenhuma outra transação; por isso, ataques de repetição (replay attacks) são impossíveis.
A questão é: como derivar uma chave DUKPT capaz de desbloquear uma determinada transação? De forma geral, são necessários o Número de Série da Chave (KSN) referente à transação, além de um valor especial chamado IPEK — a chave inicial injetada no leitor de cartão de crédito. O IPEK, por sua vez, é derivado de uma chave ultrassecreta (que jamais é injetada em um leitor de cartão) denominada BDK (Base Derivation Key). Ao contrário da BDK, o IPEK é exclusivo de um determinado dispositivo físico. (Uma única BDK pode ser a origem de diversos IPEKs únicos.) Caso você não saiba qual é o IPEK do seu dispositivo — e não há motivo para sabê-lo, já que o IPEK nunca é registrado em lugar algum —, é possível derivá-lo a partir de um KSN e de uma Base Derivation Key, utilizando a técnica descrita na Parte I deste artigo.
A derivação de uma chave de sessão (também chamada de chave de trabalho, ou simplesmente "chave de dados") é melhor compreendida como um processo de 3 etapas, descritas a seguir:
1. Use a BDK e o KSN para derivar o IPEK. (Consulte a Parte I deste artigo para obter detalhes sobre como fazer isso.)
2. Use o algoritmo de derivação de chaves ANSI X9.24 (DUKPT) para derivar uma chave base, ou "chave derivada" inicial, a partir do KSN e do IPEK.
3. Converta a chave derivada da Etapa 2 em Data Key, PIN Key ou MAC Key, conforme sua preferência. (Observe que, embora a maioria dos leitores de cartão de crédito seja configurada para usar a chave variante de Dados como chave de sessão de transação, alguns são, na verdade, configurados para usar a variante PIN.)
Vamos verificar o que está envolvido na obtenção da "chave derivada" (etapa 2), pois esta é, de longe, a parte mais trabalhosa do processo de 3 etapas. Depois de obter a chave derivada, discutiremos como transformá-la em uma variante de Dados, PIN ou MAC, o que é relativamente simples.
Usaremos bastante pseudocódigo a seguir, mas fique tranquilo: você pode encontrar o código-fonte completo e funcional (em JavaScript) para todas as etapas a seguir em nosso popular Ferramenta de Criptografia/Descriptografia. (Experimente agora, caso ainda não o tenha feito. É uma página web autossuficiente que funciona em qualquer navegador moderno.)
Derivando uma Chave
Para derivar a chave base a partir da qual uma variante de Dados, PIN ou MAC pode ser criada, você precisa começar com um KSN de transação e um IPEK. Depois de obtê-los (novamente: consulte Parte I desta série), faça o seguinte:
1. Obtenha os 8 bytes inferiores (mais à direita) do seu KSN de 10 bytes. Descarte os dois bytes superiores.
2. Crie uma variável BaseKSN para armazenar uma versão mascarada do seu KSN de 8 bytes. Obtenha a versão mascarada aplicando a operação AND ao KSN de 8 bytes da Etapa 1 com o valor (hexadecimal) 0xFFFFFFFFFFE00000.
3. Obtenha os bits de contador do seu KSN original de 10 bytes (não mascarado!) aplicando a operação AND nos três bytes inferiores com 0x1FFFFF. (Lembre-se de que os 21 bits inferiores de um KSN compõem o contador de transações.) Armazenaremos isso em uma variável chamada (o que mais seria?) counter.
4. Copie seu IPEK de 16 bytes para uma variável chamada curKey.
5. Agora precisamos configurar um loop. A cada iteração, vamos inspecionar os bits do counter (começando pelo bit mais alto, ou seja, o 21º bit; na segunda passagem, verificaremos o 20º bit; depois o 19º; e assim por diante). Sempre que encontrarmos um bit ativado, vamos aplicar um OR com o BaseKSN e, em seguida, chamar generateKey() para atualizar curKey. O BaseKSN acumulará bits a cada iteração do loop, e o valor de curKey será atualizado a cada bit ativado do counter encontrado.
O que generateKey() faz? Boa pergunta! Se sua linguagem de programação suportar aritmética BigInteger, o código terá uma aparência semelhante a esta:
Certo. Você pode ver que a chave de 16 bytes é mascarada e, em seguida, utilizada para criptografar o valor de 8 bytes do ksn , a fim de obter a metade esquerda (os 8 bytes à esquerda) de uma nova chave. A metade direita da nova chave é uma cifra criada a partir do mesmo ksn, porém utilizando uma chave sem máscara.
Por fim, você precisa saber como é a função encryptRegister() . Veja como ela se apresenta:
Observe que o Cipher Block Chaining não tem significado prático aqui, pois estamos cifrando um valor de 8 bytes (um único bloco de dados). Não há nada a "encadear." Ele está incluído no código simplesmente porque a rotina de cifragem exige um parâmetro que indica se o encadeamento deve ou não ser utilizado.
Observe também que utilizamos uma chave de 8 bytes para realizar a cifragem. O TDES opera em modo DES simples quando a chave tem apenas 8 bytes. Isso ocorre porque, no Triple DES, uma chave de 8 bytes resultaria em um ciclo cifrar/decifrar/cifrar equivalente a uma única operação de cifragem.
Em termos simples, o que acontece é que a rotina utiliza os 8 bytes superiores de uma chave de 16 bytes para cifrar um valor especial, obtido por meio da operação XOR entre os 8 bytes inferiores da chave e o ksn (de 8 bytes). O resultado é um hash unidirecional do ksn.
Reunindo tudo, o resultado é que o loop do Passo 5 acima produz um valor curKey que se torna uma chave base a partir da qual podemos derivar variantes de Data, PIN ou MAC. (O loop do Passo 5 é, ou deveria ser, parte de uma função que retorna curKey, que é a chave base.)
É hora de examinar com mais detalhes as três opções de "variante de chave".
Criando Variantes de Chave Data, PIN e MAC
O ANSI X9.24 permite que uma chave DUKPT assuma uma de três formas finais, denominadas variantes. As formas são MAC, PIN e Data. Vamos deixar para discutir os usos de cada tipo de chave em outro momento, concentrando-nos aqui em como elas são criadas.
O ponto de partida para qualquer uma das variantes é uma chave base DUKPT (a chave derivada que chamamos de curKey na Etapa 5 descrita acima). Para obter a variante MAC, basta aplicar XOR à chave base (a "chave derivada") com uma constante especial:
A variante PIN é criada de forma semelhante, mas utilizando uma constante diferente:
A variante de Dados requer ainda outra constante:
Para as variantes MAC e PIN, a operação XOR constitui a etapa final na criação da chave de sessão correspondente. Para a variante de Dados, é prática comum realizar uma etapa adicional, envolvendo um hash unidirecional (para eliminar qualquer possibilidade de alguém reverter uma chave de Dados em uma chave MAC). Em pseudocódigo:
Em termos simples: primeiro, obtenha uma versão de 24 bytes da sua chave derivada, utilizando o método de expansão EDE3. (Isso significa simplesmente copiar os primeiros 8 bytes de uma chave de 16 bytes para o final da chave, criando uma chave de 24 bytes na qual os primeiros e os últimos 8 bytes são idênticos.) Use essa chave para criptografar com TDES os primeiros 8 bytes da sua chave derivada de 16 bytes, gerando assim um bloco cifrado de 8 bytes — essa é a metade esquerda da chave de dados final. Para criar a metade direita, use a mesma chave de 24 bytes para criptografar os 8 bytes finais da chave derivada. Combine os dois blocos cifrados de 8 bytes (partes esquerda e direita) e o processo estará concluído.
Valores de Referência Conhecidos
Se você estiver tentando reproduzir este processo por conta própria, pode ser útil verificar seus resultados com alguns valores de referência conhecidos. Comece com uma BDK de 16 bytes igual a 0123456789ABCDEFFEDCBA9876543210 (hexadecimal), que é o valor de chave de teste amplamente utilizado. Use um valor de KSN de teste igual a 629949012C0000000003. Com esses dois valores, você deverá derivar um IPEK igual a D2943CCF80F42E88E23C12D1162FD547. (Consulte Parte I deste artigo caso queira ver como derivar o IPEK.)
Partindo do IPEK mencionado acima, você deverá obter os seguintes valores ao derivar uma "chave derivada" (ou chave base DUKPT):
Na primeira passagem pelo "if" do loop do contador KSN, seu BaseKSN será 49012C0000000002 e curKey se tornará B58CDA5C7A1E9FF5E7335B988626D01A após generateKey().
Na segunda passagem pelo "if" do loop do contador, você terá processado os dois bits "ON" do contador e, portanto, seu BaseKSN será 49012C0000000003 e o curKey resultante será 841AB7B94ED086EBC2B8A8385DA7DFCA. (Lembre-se: você está aplicando OR com os bits do contador, do MSB para o LSB, no BaseKSN. Se o contador terminar em 0x0F, o BaseKSN passará de 49012C0000000008 para 49012C000000000C, depois para 49012C000000000E e, por fim, para 49012C000000000F conforme os bits são aplicados sucessivamente.)
Sua "chave derivada" será, portanto, 841AB7B94ED086EBC2B8A8385DA7DFCA.
Após o XOR com a constante de variante de dados, a chave derivada será alterada para 841AB7B94E2F86EBC2B8A8385D58DFCA.
Após cifrar as metades superior e inferior do último valor, utilizando uma chave de expansão EDE3 de 841AB7B94E2F86EBC2B8A8385D58DFCA841AB7B94E2F86EB, você deverá obter uma chave de dados final de F739AEF595D3877F731782D28BB6AC4F. Ou seja: usando o valor de chave EDE3 de 24 bytes para cifrar 841AB7B94E2F86EB, você deverá obter o cifrado F739AEF595D3877F, e usando a mesma chave para cifrar C2B8A8385D58DFCA, você deverá obter o cifrado 731782D28BB6AC4F. Concatene os cifrados e o processo estará concluído. Você agora possui uma chave de 16 bytes com a qual pode descriptografar os dados da transação cujo KSN era 629949012C0000000003.
Código de Exemplo: A Ferramenta de Criptografia/Descriptografia da ID TECH
Para acessar o código-fonte completo de todas as rotinas de derivação de chaves DUKPT discutidas aqui, não deixe de baixar (e examinar o código-fonte de) nossa ferramenta baseada em HTML e JavaScript Ferramenta de Criptografia/Descriptografia, que pode calcular IPEKs, derivar todas as 3 variantes de chave DUKPT, criptografar ou descriptografar dados usando TDES ou AES, e muito mais. Você pode usar o excelente conjunto de ferramentas do console de desenvolvedor do Chrome para percorrer o código da ferramenta em tempo real, inspecionar valores de variáveis conforme são alterados, definir pontos de interrupção, entre outros recursos. É um recurso de aprendizado extraordinário. E é gratuito! Portanto, baixe a Ferramenta de Criptografia/Descriptografia, experimente e compartilhe com seus colegas. Até onde sei, é a única implementação DUKPT em JavaScript puro disponível na Web.
