Estamos revisando estes procedimentos. Pessoas técnicas podem encontrar ajustes em códigos de erro ou mapeamentos de payload; valide com os logs e o OpenAPI mais recente. Pessoas não técnicas podem continuar usando o passo a passo e acionar o time de suporte caso algo pareça diferente do descrito.
🔐 Geração de Pinblock ISO-0
Este documento descreve o processo completo para gerar um Pinblock no formato ISO-0 (ISO 9564-1 Format 0), necessário para realizar transações de venda com senha criptografada.
🎯 O que é Pinblock?
O Pinblock (PIN Block) é um método padrão de criptografia de senha (PIN) usado em transações financeiras. Ele combina o PIN do cliente com o número do cartão (PAN) e aplica criptografia 3DES para garantir a segurança da transação.
Características
- Formato: ISO-0 (ISO 9564-1 Format 0)
- Padding: Caractere F
- Criptografia: 3DES ECB
- Tamanho: 16 bytes (32 caracteres hexadecimais)
🔄 Processo de Geração
A geração do Pinblock envolve 3 passos principais:
📝 Passo a Passo
Dados de Entrada
Para o exemplo, vamos usar:
- PAN (Número do Cartão):
9357229116678858 - Senha (PIN):
8374 - Working Key:
BF21C1AB96E97E1CF2D9EFAE4A9086F6458B9E6118B1AF8C(obtida via API)
Passo 1: Formatação do PIN
Concatene os seguintes elementos para formar uma string de 16 caracteres hexadecimais:
04- Prefixo fixo indicando o formato ISO-0- Tamanho do PIN - Número de dígitos do PIN (4 neste exemplo)
- PIN - A senha do cliente
- Padding F - Preencha o restante com
Faté completar 16 caracteres
Exemplo:
Prefixo: 04
Tamanho: 4
PIN: 8374
Padding: FFFFFFFFFFF
Resultado Passo 1: 04 8374 FFFFFFFFFFF
Formatado: 04 83 74 FF FF FF FF FF
Em hexadecimal: 0 4 8 3 7 4 F F F F F F F F F F
Passo 2: Formatação do PAN
Extraia os 12 dígitos centrais do PAN (posições 4 a 15, desconsiderando os dígitos de controle) e formate:
0000- Prefixo fixo- 12 dígitos do PAN - Posições 4 até 15 do número do cartão
Exemplo:
PAN completo: 9357229116678858
Posições 4-15: 722911667885
Prefixo: 0000
PAN parcial: 722911667885
Resultado Passo 2: 0000722911667885
Em hexadecimal: 0 0 0 0 7 2 2 9 1 1 6 6 7 8 8 5
Passo 3: Operação XOR
Aplique a operação XOR bit a bit entre os resultados do Passo 1 e Passo 2:
Passo 1: 0 4 8 3 7 4 F F F F F F F F F F
Passo 2: 0 0 0 0 7 2 2 9 1 1 6 6 7 8 8 5
─────────────────────────────────
XOR: 0 4 8 3 0 6 D 6 E E 9 9 8 7 7 A
Resultado (Pinblock em Claro): 048306D6EE99877A
Validando o XOR
Você pode validar o XOR usando a Calculadora do Windows no modo Programador:
Exemplo: F XOR 6 = 9
F (hex) = 1111 (binário)
6 (hex) = 0110 (binário)
────
XOR 1001 (binário) = 9 (hex)
Passo 4: Criptografia 3DES
Aplique criptografia 3DES no modo ECB usando a Working Key obtida através da API:
Exemplo:
Pinblock em Claro: 048306D6EE99877A
Working Key: BF21C1AB96E97E1CF2D9EFAE4A9086F6458B9E6118B1AF8C
Algoritmo: 3DES ECB (sem padding adicional)
Resultado: a760654cfeeffd24
Pinblock Criptografado Final: a760654cfeeffd24
💻 Implementação
JavaScript/Node.js
const crypto = require('crypto');
/**
* Gera um Pinblock ISO-0 criptografado
* @param {string} pin - Senha do cliente (4-12 dígitos)
* @param {string} pan - Número do cartão (PAN)
* @param {string} workingKey - Chave de trabalho (hex string)
* @returns {string} Pinblock criptografado em hexadecimal
*/
function gerarPinblockISO0(pin, pan, workingKey) {
// Validações
if (!pin || pin.length < 4 || pin.length > 12) {
throw new Error('PIN deve ter entre 4 e 12 dígitos');
}
if (!pan || pan.length < 13) {
throw new Error('PAN inválido');
}
// Passo 1: Formatar PIN
const pinLength = pin.length.toString(16).padStart(2, '0');
const passo1 = ('04' + pin + 'F'.repeat(14 - pin.length)).toUpperCase();
// Passo 2: Formatar PAN (posições 4 a 15)
const panPart = pan.substring(pan.length - 13, pan.length - 1);
const passo2 = ('0000' + panPart).substring(0, 16);
// Passo 3: XOR
let pinblockClaro = '';
for (let i = 0; i < 16; i++) {
const xor = parseInt(passo1[i], 16) ^ parseInt(passo2[i], 16);
pinblockClaro += xor.toString(16).toUpperCase();
}
console.log('Passo 1 (PIN formatado):', passo1);
console.log('Passo 2 (PAN formatado):', passo2);
console.log('Passo 3 (XOR - Pinblock em claro):', pinblockClaro);
// Passo 4: Criptografar com 3DES
const key = Buffer.from(workingKey, 'hex');
const cipher = crypto.createCipheriv('des-ede3', key, null);
cipher.setAutoPadding(false);
const pinblockBuffer = Buffer.from(pinblockClaro, 'hex');
let encrypted = cipher.update(pinblockBuffer);
encrypted = Buffer.concat([encrypted, cipher.final()]);
const pinblockCriptografado = encrypted.toString('hex');
console.log('Pinblock Criptografado:', pinblockCriptografado);
return pinblockCriptografado;
}
// Exemplo de uso
const pin = '8374';
const pan = '9357229116678858';
const workingKey = 'BF21C1AB96E97E1CF2D9EFAE4A9086F6458B9E6118B1AF8C';
const pinblock = gerarPinblockISO0(pin, pan, workingKey);
console.log('\nPinblock Final:', pinblock);
// Resultado esperado: a760654cfeeffd24
Python
from Crypto.Cipher import DES3
import binascii
def gerar_pinblock_iso0(pin, pan, working_key):
"""
Gera um Pinblock ISO-0 criptografado
Args:
pin (str): Senha do cliente (4-12 dígitos)
pan (str): Número do cartão (PAN)
working_key (str): Chave de trabalho (hex string)
Returns:
str: Pinblock criptografado em hexadecimal
"""
# Validações
if not pin or len(pin) < 4 or len(pin) > 12:
raise ValueError('PIN deve ter entre 4 e 12 dígitos')
if not pan or len(pan) < 13:
raise ValueError('PAN inválido')
# Passo 1: Formatar PIN
passo1 = f"04{pin}{'F' * (14 - len(pin))}"
# Passo 2: Formatar PAN (posições 4 a 15)
pan_part = pan[-13:-1]
passo2 = f"0000{pan_part}"[:16]
# Passo 3: XOR
pinblock_claro = ''
for i in range(16):
xor = int(passo1[i], 16) ^ int(passo2[i], 16)
pinblock_claro += format(xor, 'X')
print(f'Passo 1 (PIN formatado): {passo1}')
print(f'Passo 2 (PAN formatado): {passo2}')
print(f'Passo 3 (XOR - Pinblock em claro): {pinblock_claro}')
# Passo 4: Criptografar com 3DES
key = binascii.unhexlify(working_key)
cipher = DES3.new(key, DES3.MODE_ECB)
pinblock_bytes = binascii.unhexlify(pinblock_claro)
encrypted = cipher.encrypt(pinblock_bytes)
pinblock_criptografado = binascii.hexlify(encrypted).decode('utf-8')
print(f'Pinblock Criptografado: {pinblock_criptografado}')
return pinblock_criptografado
# Exemplo de uso
pin = '8374'
pan = '9357229116678858'
working_key = 'BF21C1AB96E97E1CF2D9EFAE4A9086F6458B9E6118B1AF8C'
pinblock = gerar_pinblock_iso0(pin, pan, working_key)
print(f'\nPinblock Final: {pinblock}')
# Resultado esperado: a760654cfeeffd24
Java
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.HexFormat;
public class PinblockISO0 {
public static String gerarPinblockISO0(String pin, String pan, String workingKey)
throws Exception {
// Validações
if (pin == null || pin.length() < 4 || pin.length() > 12) {
throw new IllegalArgumentException("PIN deve ter entre 4 e 12 dígitos");
}
if (pan == null || pan.length() < 13) {
throw new IllegalArgumentException("PAN inválido");
}
// Passo 1: Formatar PIN
StringBuilder passo1 = new StringBuilder("04");
passo1.append(pin);
while (passo1.length() < 16) {
passo1.append('F');
}
// Passo 2: Formatar PAN (posições 4 a 15)
String panPart = pan.substring(pan.length() - 13, pan.length() - 1);
String passo2 = ("0000" + panPart).substring(0, 16);
// Passo 3: XOR
StringBuilder pinblockClaro = new StringBuilder();
for (int i = 0; i < 16; i++) {
int xor = Character.digit(passo1.charAt(i), 16) ^
Character.digit(passo2.charAt(i), 16);
pinblockClaro.append(Integer.toHexString(xor).toUpperCase());
}
System.out.println("Passo 1 (PIN formatado): " + passo1);
System.out.println("Passo 2 (PAN formatado): " + passo2);
System.out.println("Passo 3 (XOR - Pinblock em claro): " + pinblockClaro);
// Passo 4: Criptografar com 3DES
byte[] keyBytes = HexFormat.of().parseHex(workingKey);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] pinblockBytes = HexFormat.of().parseHex(pinblockClaro.toString());
byte[] encrypted = cipher.doFinal(pinblockBytes);
String pinblockCriptografado = HexFormat.of().formatHex(encrypted);
System.out.println("Pinblock Criptografado: " + pinblockCriptografado);
return pinblockCriptografado;
}
public static void main(String[] args) {
try {
String pin = "8374";
String pan = "9357229116678858";
String workingKey = "BF21C1AB96E97E1CF2D9EFAE4A9086F6458B9E6118B1AF8C";
String pinblock = gerarPinblockISO0(pin, pan, workingKey);
System.out.println("\nPinblock Final: " + pinblock);
// Resultado esperado: a760654cfeeffd24
} catch (Exception e) {
e.printStackTrace();
}
}
}
🔗 Usando na API de Venda
Após gerar o Pinblock, utilize-o no campo senhaCriptografada da API de venda:
{
"estabelecimento": "12345",
"codigoMaquina": "PDV001",
"cartao": {
"tarja": "9357229116678858",
"cvv2": "000",
"senhaCriptografada": "a760654cfeeffd24"
},
"nsu": "123456789",
"venda": {
"valor": 150.00,
"quantidadeParcelas": 1,
"tipoParcelamento": "A"
}
}
Exemplo de Chamada cURL
curl --location 'https://api.credsystem.com/v1/venda' \
--header 'Authorization: Bearer SEU_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"estabelecimento": "12345",
"codigoMaquina": "PDV001",
"cartao": {
"tarja": "9357229116678858",
"cvv2": "000",
"senhaCriptografada": "a760654cfeeffd24"
},
"nsu": "123456789",
"venda": {
"valor": 150.00,
"quantidadeParcelas": 1,
"tipoParcelamento": "A"
}
}'
🔑 Obtendo a Working Key
A Working Key deve ser obtida através da API de criptografia antes de gerar o Pinblock:
// Exemplo de obtenção da Working Key
const obterWorkingKey = async () => {
const response = await fetch('https://api.credsystem.com/v1/crypto/working-key', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
estabelecimento: '12345',
terminal: 'PDV001'
})
});
const data = await response.json();
return data.workingKey;
};
🧪 Ferramentas de Validação
Validar XOR Online
Use a Calculadora do Windows no modo Programador:
- Abra a Calculadora
- Vá em Exibir → Programador
- Selecione HEX
- Digite o primeiro valor
- Clique em XOR
- Digite o segundo valor
- Veja o resultado
Validar 3DES Online
Você pode validar a criptografia 3DES em: http://tripledes.online-domain-tools.com/
Configurações:
- Mode: ECB
- Key: Sua Working Key (hex)
- Input: Pinblock em claro (hex)
- Output: Deve corresponder ao seu resultado
⚠️ Considerações de Segurança
Boas Práticas
- ✅ Nunca armazene o PIN ou Pinblock em claro
- ✅ Use HTTPS para todas as comunicações
- ✅ Renove a Working Key periodicamente
- ✅ Implemente timeout para entrada de senha
- ✅ Limite tentativas de senha incorreta
- ✅ Use bibliotecas criptográficas confiáveis
Não Faça
- ❌ Não envie o PIN em claro pela rede
- ❌ Não registre o PIN ou Pinblock em logs
- ❌ Não use chaves fixas em produção
- ❌ Não implemente criptografia própria
- ❌ Não armazene Working Keys no frontend
🔍 Troubleshooting
Problemas Comuns
| Problema | Causa Provável | Solução |
|---|---|---|
| Pinblock diferente do esperado | Erro no XOR ou formatação | Validar cada passo individualmente |
| Erro de criptografia | Working Key incorreta | Verificar formato hex da chave |
| API rejeita Pinblock | Formato incorreto | Confirmar formato ISO-0 e 3DES ECB |
| Erro de padding | PIN muito curto/longo | Validar tamanho do PIN (4-12 dígitos) |
Validação Passo a Passo
// Debug: Validar cada etapa
console.log('PIN:', pin);
console.log('PAN:', pan);
console.log('Passo 1:', passo1);
console.log('Passo 2:', passo2);
console.log('Pinblock Claro:', pinblockClaro);
console.log('Working Key:', workingKey);
console.log('Pinblock Criptografado:', pinblockCriptografado);
📚 Referências
- ISO 9564-1: Personal Identification Number (PIN) management and security
- ANSI X9.8: PIN Management and Security
- 3DES: Triple Data Encryption Standard (FIPS 46-3)
🆘 Suporte
Para dúvidas ou problemas com geração de Pinblock:
- 📧 Email: suporte.tecnico@credsystem.com.br
- 📞 Telefone: 0800-XXX-XXXX
- 💬 Chat: Disponível no portal do desenvolvedor
- 📖 Documentação: API de Venda
Última atualização: Dezembro 2024