ID TECH
Contato
Todos os posts técnicos

Post Técnico

Como Descriptografar Dados de Cartão de Crédito, Parte II

Os clientes frequentemente perguntam: Como posso descriptografar os dados provenientes do 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 empregada. Com essas informações, é possível descriptografar os dados usando a 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). É importante 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 replay são impossíveis.

A questão é: como derivar uma chave DUKPT capaz de desbloquear uma determinada transação? A resposta é: em linhas gerais, é necessário ter o Número de Série da Chave (KSN) da 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 do BDK, o IPEK é exclusivo de um determinado dispositivo físico. (Um único BDK pode ser a origem de muitos IPEKs exclusivos.) Caso não conheça o IPEK do seu dispositivo — e não há motivo para que o conheça, pois 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 (às vezes chamada de chave de trabalho, ou simplesmente "chave de dados") é melhor compreendida como um processo de 3 etapas. As etapas são:

1. Use o BDK e o KSN para derivar o IPEK. (Consulte Parte I deste artigo para obter detalhes sobre como fazer isso.)

2. Utilize 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 uma 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 Data como chave de sessão de transação, alguns são, de fato, configurados para usar a variante PIN.)

Vejamos 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. Assim que tivermos a chave derivada, abordaremos como transformá-la em uma variante Data, PIN ou MAC, o que é relativamente simples.

Utilizaremos 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 independente que funciona em qualquer navegador moderno.)

Derivando uma Chave

Para derivar a chave base a partir da qual uma variante Data, PIN ou MAC pode ser criada, você precisa começar com um KSN de transação e um IPEK. Assim que os tiver (novamente: consulte Parte I desta série), siga este procedimento:

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 entre o KSN de 8 bytes da Etapa 1 e o valor (hexadecimal) 0xFFFFFFFFFFE00000.

3. Obtenha os bits de contador do seu KSN original de 10 bytes (não 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 quê mais?) counter.

4. Copie seu IPEK de 16 bytes em uma variável chamada curKey.

5. Agora precisamos configurar um loop. A cada iteração, inspecionaremos os bits do contador (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, aplicaremos um OR ao BaseKSN e, em seguida, chamaremos 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 contador que for encontrado.

O que generateKey() faz? Boa pergunta! Se sua linguagem de programação suportar operações com BigInteger, o código terá uma aparência semelhante a esta:

Entendido. Você pode observar que a chave de 16 bytes é mascarada e, em seguida, utilizada para cifrar o valor de 8 bytes ksn , obtendo assim a metade esquerda (os 8 bytes à esquerda) de uma nova chave. A metade direita da nova chave é um cifrador gerado a partir do mesmo ksn, porém utilizando uma chave sem máscara.

Por fim, você precisa saber o que encryptRegister() é assim. Veja a seguir:

Observe que o Cipher Block Chaining não tem relevância prática aqui, pois estamos cifrando um valor de 8 bytes (um único bloco de dados). Não há nada a ser "encadeado". Ele está incluído no código simplesmente porque a rotina de cifração exige um parâmetro que indica se o encadeamento está habilitado ou não.

Observe também que estamos utilizando uma chave de 8 bytes para realizar a cifração. O TDES opera como DES simples quando a chave tem apenas 8 bytes. Isso ocorre porque, no Triple DES, uma chave de 8 bytes resultaria em um ciclo de cifrar/decifrar/cifrar equivalente a uma única operação de cifração.

Em termos simples, o que ocorre é que a rotina utiliza os 8 bytes superiores de uma chave de 16 bytes para cifrar um valor especial, obtido pelo XOR entre os 8 bytes inferiores da chave e o ksn (de 8 bytes). O resultado é um hash unidirecional do ksn.

Juntando tudo, o resultado é que o laço 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 laço do Passo 5 faz parte, ou deveria fazer parte, de uma função que retorna curKey, a qual representa a chave base.)

É hora de examinar mais detalhadamente essas 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: MAC, PIN e Data. Deixemos de lado a discussão sobre para que cada tipo de chave é utilizado e concentremo-nos 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 no Passo 5 acima). Para obter a variante MAC, basta aplicar XOR entre a chave base (a "chave derivada") e uma constante especial:

A variante PIN é criada de forma semelhante, porém utilizando uma constante diferente:

A variante Data 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 Data, é habitual realizar uma etapa adicional, que envolve um hash unidirecional (para eliminar qualquer possibilidade de alguém reverter uma chave Data 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 via TDES os primeiros 8 bytes da sua chave derivada de 16 bytes, gerando assim um 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. Una os dois cifrados de 8 bytes (partes esquerda e direita) e o processo está concluído.

Valores de Referência Conhecidos

Se estiver tentando reproduzir este processo, convém verificar seus resultados com base em valores de referência conhecidos. Para isso, utilize um BDK de 16 bytes igual a 0123456789ABCDEFFEDCBA9876543210 (hexadecimal), que é o valor de chave de teste amplamente utilizado. Experimente 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 se quiser ver como derivar o IPEK.)

Partindo do IPEK mencionado anteriormente, 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, o seu BaseKSN será 49012C0000000002 e curKey passará a ser B58CDA5C7A1E9FF5E7335B988626D01A após generateKey().

Na segunda passagem pelo "if" do loop do contador, você terá processado ambos os 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 à medida que 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 desse 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 criptografar 841AB7B94E2F86EB, você deverá obter o cifrotexto F739AEF595D3877F e, usando a mesma chave para criptografar C2B8A8385D58DFCA, deverá obter o cifrotexto 731782D28BB6AC4F. Concatene os cifrotextos e o processo está concluído. Você agora possui uma chave de 16 bytes com a qual pode descriptografar os dados da transação cujo KSN era 629949012C0000000003.

Exemplo de Código: A Ferramenta de Criptografia/Descriptografia da ID TECH

Para acessar o código-fonte completo de todas as rotinas de derivação de chave DUKPT discutidas aqui, certifique-se 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 do desenvolvedor do Chrome para percorrer o código da ferramenta em tempo real, inspecionar valores de variáveis conforme eles mudam, definir pontos de interrupção, entre outros recursos. É um recurso de aprendizado extraordinário. E é gratuito! Então, baixe a Ferramenta de Criptografia/Descriptografia, explore suas funcionalidades e compartilhe com seus colegas. Até onde sei, é a única implementação DUKPT em JavaScript puro disponível na Web.