- Se incorporó
- 16 Noviembre 2021
- Mensajes
- 455
Uno de los ingenieros del área publicó un paso a paso para dar a conocer como funciona el algoritmo que genera los códigos de seguridad de las tarjetas. Para efectos prácticos y realistas, no tiene mucha utilidad, pero no deja de ser interesante el proceso.
Información de la tarjeta
Para una tarjeta cualquiera, podemos identificar impresos o grabados a presión(hundidos) la numeración PAN y la fecha de vencimiento (en el anverso). Al reverso, el código de autorización para compras en internet y en ocasiones el código de servicio del documento.
Generación del CVV2
Para efectos prácticos llamaremos Jerry a la función generadora del cvv2.
La lógica es: Jerry nos genera en función de clave_a el código del reverso de la tarjeta, en función de sus datos.
Como Jerry nos genera el cvv2, podemos crear tarjetas fictíseas para nuestro banco imaginario, todas las que queramos, en la práctica, clave_a es desconocida, aleatoria y su vida útil comprende la vida útil del plástico.
Creación de una tarjeta imaginaria
Generemos una tarjeta imaginaria.
Conjeturas preliminares
Para quienes hubieren leido el link, llama la atención el proceso final de jerry, como solo son tomados los tres primeros digitos del resultado alfanumérico para construir el código de seguridad.
Me llama la atención que solo sean seleccionados dichos dígitos pudiéndo seleccionar posiciones aleatorias. Pero supongo que no influiría demasiado, al contrario, encarecería la generación. Tambien se pudiera pensar que CLAVE_A es indispensable pero pudiéramos removerla del proceso y reemplazarla con una variable contador incrementable dentro de una construcción repetitiva.
Información de la tarjeta
Para una tarjeta cualquiera, podemos identificar impresos o grabados a presión(hundidos) la numeración PAN y la fecha de vencimiento (en el anverso). Al reverso, el código de autorización para compras en internet y en ocasiones el código de servicio del documento.
- Número PAN (Código largo)
- CVV2 (usado para comprar en internet)
- SVC (segundo código al reverso)
- Fecha de vencimiento del documento (MM/YY)
Generación del CVV2
Para efectos prácticos llamaremos Jerry a la función generadora del cvv2.
Código:
funcion jerry(clave_a, pan, svc, venc) {
// ... DES por aquí, DES por allá
retornar cvv2;
}
La lógica es: Jerry nos genera en función de clave_a el código del reverso de la tarjeta, en función de sus datos.
Como Jerry nos genera el cvv2, podemos crear tarjetas fictíseas para nuestro banco imaginario, todas las que queramos, en la práctica, clave_a es desconocida, aleatoria y su vida útil comprende la vida útil del plástico.
Creación de una tarjeta imaginaria
Generemos una tarjeta imaginaria.
Código:
PAN: 1234561234567898
SVC: 000
VENC: 01/22
CLAVE_A: FEC42D5BDDC3893B3860AAD242C879C3
// Calcular CVV2
jerry(CLAVE_A, PAN, SVC, VENC) // 341
Conjeturas preliminares
- Dado que CVV2 se genera en función de CLAVE_A, para calcularlo bastaría con conocer CLAVE_A
- Dado que CLAVE_A es única para cada documento es incalculable/ingenerable
- Desconocemos del método por el que se genera CLAVE_A, por lo que el punto anterior se refuerza
Para quienes hubieren leido el link, llama la atención el proceso final de jerry, como solo son tomados los tres primeros digitos del resultado alfanumérico para construir el código de seguridad.
Código:
funcion jerry(clave_a, pan, svc, venc) {
// ...
resultado_alfa_numerico = "AD341CB17547F331";
resultado_numerico = "34117547331";
cvv2 = "341";
retornar cvv2;
}
Me llama la atención que solo sean seleccionados dichos dígitos pudiéndo seleccionar posiciones aleatorias. Pero supongo que no influiría demasiado, al contrario, encarecería la generación. Tambien se pudiera pensar que CLAVE_A es indispensable pero pudiéramos removerla del proceso y reemplazarla con una variable contador incrementable dentro de una construcción repetitiva.
Código:
v_pan: 1234561234567898;
v_svc: 000;
v_venc: 01/22;
v_fin = 10^4; // 10 mil
v_i_clave_a = 1;
v_cvv2 = "341";
para v_i=0 hasta v_fin incrementar v_i en 1 entonces
v_clave_a = convertir_hex(v_i_clave_a); // Convierte el entero en hexadecimal
v_clave_a = rellenar_izquierda(v_clave_a, 32, "0"); // Rellena con ceros a la izquierda
v_cvv2_generado = jerry(v_clave_a, v_pan, v_svc, v_venc);
si v_cvv2 == v_cvv2_generado entonces
imprimir(v_clave_a);
fin si;
fin para
Código:
// Resultado (24 colisiones en 10 mil iteraciones)
341CE0D60E6198C1 -> 34106061981 -> 341
341CE0D60E6198C1 -> 34106061981 -> 341
341CE0D60E6198C1 -> 34106061981 -> 341
341CE0D60E6198C1 -> 34106061981 -> 341
ED34137F5535BF8D -> 3413755358 -> 341
ED34137F5535BF8D -> 3413755358 -> 341
ED34137F5535BF8D -> 3413755358 -> 341
ED34137F5535BF8D -> 3413755358 -> 341
F34B1F49199F7D74 -> 34149199774 -> 341
F34B1F49199F7D74 -> 34149199774 -> 341
3A419B21D08F2ACC -> 341921082 -> 341
3A419B21D08F2ACC -> 341921082 -> 341
F34B1F49199F7D74 -> 34149199774 -> 341
F34B1F49199F7D74 -> 34149199774 -> 341
3A419B21D08F2ACC -> 341921082 -> 341
3A419B21D08F2ACC -> 341921082 -> 341
34BAB10B1580885A -> 34101580885 -> 341
34BAB10B1580885A -> 34101580885 -> 341
34BAB10B1580885A -> 34101580885 -> 341
34BAB10B1580885A -> 34101580885 -> 341
3415E1C3D1B63018 -> 341513163018 -> 341
3415E1C3D1B63018 -> 341513163018 -> 341
3415E1C3D1B63018 -> 341513163018 -> 341
3415E1C3D1B63018 -> 341513163018 -> 341
Última modificación: