Cifrado GrimmXtract

20 09 2011
En muchas ocasiones tendremos la necesidad de ocultar cierta información de origen a ojos de sistemas informáticos de paso hasta depositarla en el destino.
Existen numerosísimos sistemas de cifrado, más complicados unos que otros, unos más simples que otros de “romper”. Denominando “romper” a la acción de encontrar la clave (o protocolo) de cifrado necesarios para interpretar el mensaje o información de forma correctos.
 
Ejemplo-1 (plano)


 
En una ocasión, me topé con la necesidad de intervenir en un cauce de información entre una aplicación abierta y un proceso centralizado (reservado). En esta necesidad, teníamos que priorizar la velocidad de proceso frente al recurso de espacio, es decir, los mensajes de media se estimaban muy cortos y por contra, no queríamos retrasar el proceso general al añadirle los procesos de cifrado o descrifrado.
 
Me inventé un método de cifrado que denominé GrimmXtract (extracción Grimm).


La situación era la siguiente:
          Una aplicación en Excel para recoger la información con formularios y que permite realizar un envío de la información como un anexo TXT en un email a un buzón centralizado.
          Un daemon recopila los correos (identificándolos por el asunto) y los agrupa, enviándolos vía FTP al Mainframe.
          Tras la transferencia FTP, se ejecutan los procesos planificados en el host para proceder a cargar los datos recibidos.
 
De entre todos los posibles algoritmos ideé uno en el que, en detrimento del espacio “ensucia” el contenido, haciéndolo inteligible a ojos de quien no conozca este protocolo de cifrado.
La técnica usada es bien sencilla.
Para cada carácter de entrada, se añade a la salida, se añade también un número que representará un salto de 1 a 9 posiciones adicionales, y se termina completando ese mismo número de chars aleatorios, y vuelta a empezar.
El proceso de lectura es bien sencillo. A la inversa, leemos un char de entrada, leemos el número de posiciones a saltar y las saltamos en la lectura, etc…
 
Añado un ejemplo, donde podemos observar como un texto cifrado se interpreta para componer el texto original, mucho más legible donde vamos a parar.
 


 
 
 
En este trabajo, la aplicación distribuida estaba desarrollada en Excel, por lo que se decidió añadir el componente de cifrado como un módulo añadido en visual Basic.
 
Sub crypt()
 
Dim ByteC As Byte
Dim MiCadena, charac
Dim MiCadena3 As Variant
Dim MiCadena2(30180)
Dim k, k2 As Integer
Dim i, ii As Integer
Dim r As Integer
Randomize
dir_trabajo = Worksheets(“Menu”).Cells(40, 3).Value
ChDir dir_trabajo
fic_trabajo = “Datos” & “.txt”
fic_trabajo2 = “Datos” & “.tmp”
fic_trabajo3 = “Datos” & “.bin”
Worksheets(“Menu”).Cells(40, 13).Value = dir_trabajo & “\” & fic_trabajo
Worksheets(“Menu”).Cells(140, 13).Value = dir_trabajo & “\” & fic_trabajo2
Open fic_trabajo For Binary Access Read Lock Write As #1
Open fic_trabajo2 For Binary Access Write Lock Read As #2
Get #1, , ByteC
Do While Not EOF(1)
Put #2, , ByteC
i = 0
r = (Rnd * 8) + 1
Put #2, , CByte(48 + r)
Do While (i r)
ByteC = CByte((Rnd * 255))
If ByteC Chr(13) And ByteC Chr(10) Then
Put #2, , ByteC
i = i + 1
End If
Loop
Get #1, , ByteC
Loop
Close #1
Close #2
Open fic_trabajo2 For Binary Access Read Lock Write As #4
Open fic_trabajo3 For Output Shared As #5
ii = 0
MiCadena = “”
Do While Not EOF(4)
Get #4, , ByteC
MiCadena = MiCadena & Chr(ByteC)
ii = Len(MiCadena)
If ii > 30180 Then
Print #5, MiCadena
MiCadena = “”
End If
Loop
Print #5, MiCadena
Close #4
Close #5
Open fic_trabajo3 For Append Shared As #3
Print #3,
Close #3
 
Set fs = CreateObject(“Scripting.FileSystemObject”)
fs.DeleteFile Worksheets(“Menu”).Cells(40, 13).Value, True
fs.DeleteFile Worksheets(“Menu”).Cells(140, 13).Value, True
Worksheets(“Menu”).Cells(40, 13).Value = dir_trabajo & “\” & fic_trabajo3
End Sub
 
 
En el otro extremo del cauce, en host, el primer proceso tras la recepción FTP sería el descifrado del contenido, para de este modo poder trabajar/cargar con los datos en plano. El lenguaje utilizado para este propósito fue easytrieve (adjunto código más abajo), aunque se puede diseñar el módulo de descifrado en Cobol u otro lenguaje, ya que no hacemos uso de nada más particular a parte de punteros de posicionamiento en arrays de bytes.
 
 
* FICHERO ENTRADA / CIFRADO
* longitud de 30180 = longitud-reg-max * 10
FILE FDESC
REG-LINEA 1 30180 A
* FICHERO SALIDA / DESCIFRADO
* longitud de 3018 = longitud-reg-max
FILE FSAL FB(3018 0)
SAL-LINEA 1 3018 A
* AREA DE ARRAYS DE CHARS
* se usan arrays de char y punteros para ir moviendo los CHARs
* válidos y no mover los no válidos o basura.
* W-LINEA -> W-LINEA-OUT
W-LINEA W 30180 A
W-CHAR W-LINEA 1 A OCCURS 30180
W-CHAR-N W-LINEA 1 N OCCURS 30180
W-LINEA-OUT W 3018 A
W-CHAR-OUT W-LINEA-OUT 1 A OCCURS 3018
* FLAG FIN;
FIN W 1 N VALUE 0
* FIN = 0 ; bucle normal
* FIN = 1 ; salto de linea de salida
* FIN = 2 ; fin de fichero
* FIN = 3 ; salto de linea de entrada (salto natural)
* FIN = 4 ; salto de linea de entrada (limite de registro)
* Punteros; WS-CONT
* _______/______________________
* (entrada) |_XY___ZA______________________| 30180
* \
* WS-SALTO
*
* WS-CONT-OUT
* _/____________
* (salida) |XZ____________| 3018
*
* (1) recogemos el valor X (valor desde WS-CONT)
* (2) recogemos el valor Y (valor para WS-SALTO)
* (3) saltamos ( posicion = posicion + WS-SALTO)
* (4) recogemos el valor Z (valor de WS-CONT)
* (5) recogemos el valor A (valor para WS-SALTO)
* (6) saltamos ( posicion = posicion + WS-SALTO)
*
WS-CONT W 6 N VALUE 0
WS-SALTO W 1 N VALUE 0
WS-CONT-OUT W 6 N VALUE 0
* PROCESO PRINCIPAL:
*
JOB INPUT NULL FINISH ESTADISTICAS
*——————————-
* la primera lectura del fichero …
GET FDESC
* Si el fichero no está vacio… trabajamos
IF NOT EOF FDESC
MOVE REG-LINEA TO W-LINEA
WS-CONT = 1
W-LINEA-OUT = ”
WS-CONT-OUT = 1
FIN = 0
* bucle principal, mientras haya datos de lectura / no sea fin
DO WHILE NOT EOF FDESC AND FIN < 5
* si hay salto de linea a la entrada…
IF FIN = 1
WS-SALTO = W-CHAR-N(WS-CONT)
WS-CONT = WS-CONT + WS-SALTO + 1
W-LINEA-OUT = ”
WS-CONT-OUT = 1
END-IF
* si hay salto de linea a la entrada (especial)…
IF FIN = 4
WS-SALTO = W-CHAR-N(1)
WS-CONT = WS-CONT + WS-SALTO + 1
END-IF
* inicializamos flags y salto
WS-SALTO = 0
FIN = 0
* DISPLAY ‘ WS-CONT = ‘ WS-CONT
* DISPLAY ‘ WS-CONT-OUT = ‘ WS-CONT-OUT
* DISPLAY ‘ W-CHAR = ‘ W-CHAR(WS-CONT)
* DISPLAY ‘ W-CHAR-OUT = ‘ W-CHAR-OUT
*
* recogemos el valor X (valor desde WS-CONT)
W-CHAR-OUT(WS-CONT-OUT) = W-CHAR(WS-CONT)
* si el valor recogido es limite o fin de linea,…
IF W-CHAR-OUT(WS-CONT-OUT) = X’0D’ +
OR W-CHAR-OUT(WS-CONT-OUT) = X’00’ +
OR W-CHAR-OUT(WS-CONT-OUT) = X’15’ +
OR W-CHAR-OUT(WS-CONT-OUT) = X’25’
W-CHAR-OUT(WS-CONT-OUT) = X’40’
WS-CONT-OUT = WS-CONT-OUT – 1
END-IF
* incrementamos punteros
WS-CONT-OUT = WS-CONT-OUT + 1
WS-CONT = WS-CONT + 1
* bucle interior, mientras no terminemos linea de entrada (30180)
* o lectura de valor no numerico de salto
* o salto del linea de entrada o fin de fichero
DO UNTIL FIN > 0 OR WS-CONT > 30180 +
OR W-CHAR-N(WS-CONT) X’F9′
* leemos el valor para el siguiente SALTO
WS-SALTO = W-CHAR-N(WS-CONT)
* validamos la cifra para el SALTO… ha de ser numerica
IF WS-SALTO > X’F0′ AND WS-SALTO <= X'F9'
* saltamos
WS-CONT = WS-CONT + WS-SALTO + 1
ELSE
FIN = 2
END-IF
* si todo va bien, seguimos…
IF FIN = 0
* si es fin de entrada…
IF WS-CONT > 30180
* OR WS-CONT-OUT > 3018
FIN = 3
*
ELSE
* recogemos el valor X (valor desde WS-CONT)
W-CHAR-OUT(WS-CONT-OUT) = W-CHAR(WS-CONT)
*
* si el valor recogido es fin de fichero…
IF W-CHAR-OUT(WS-CONT-OUT) = X’00’
W-CHAR-OUT(WS-CONT-OUT) = X’40’
WS-CONT-OUT = WS-CONT-OUT – 1
FIN = 2
ELSE
* si el valor recogido es fin de linea o
* si el valor recogido es retorno de carro (?)
IF W-CHAR-OUT(WS-CONT-OUT) = X’0D’ +
OR W-CHAR-OUT(WS-CONT-OUT) = X’15’ +
OR W-CHAR-OUT(WS-CONT-OUT) = X’25’
W-CHAR-OUT(WS-CONT-OUT) = X’40’
WS-CONT-OUT = WS-CONT-OUT – 1
FIN = 1
END-IF
END-IF
*
* incrementamos punteros
WS-CONT-OUT = WS-CONT-OUT + 1
WS-CONT = WS-CONT + 1
END-IF
END-IF
END-DO
* actualizar buffer de salida para posible escritura
SAL-LINEA = ”
MOVE W-LINEA-OUT TO SAL-LINEA
*
* validaciones varias;
IF WS-CONT = 30181 AND FIN = 0
FIN = 4
ELSE
IF WS-CONT > 30181
FIN = 3
ELSE
IF W-CHAR-N(WS-CONT) X’F9
FIN = 2
END-IF
END-IF
END-IF
*
DISPLAY ‘ ————————————– ‘
DISPLAY ‘ FIN = ‘ FIN
DISPLAY ‘ WS-CONT = ‘ WS-CONT
DISPLAY ‘ WS-CONT-OUT = ‘ WS-CONT-OUT
DISPLAY ‘ W-CHAR = ‘ W-CHAR(WS-CONT)
DISPLAY ‘ W-CHAR-OUT = ‘ W-CHAR-OUT(WS-CONT-OUT)
*
* si no es fin de fichero y no es fin de registro de entrada
* escribimos a la salida
IF W-CHAR-OUT(1) NE X’00’ AND FIN NE 3 AND FIN NE 2 +
AND W-CHAR(WS-CONT) NE X’40’ AND FIN NE 4
PUT FSAL
END-IF
* si no es fin de fichero y no es salto de linea
* es fin de registro de entrada
IF FIN NE 1 AND NOT EOF FDESC
*
* leemos siguiente entrada
IF FIN NE 2
GET FDESC
END-IF
*
IF FIN = 4
WS-CONT = WS-CONT – 30180
END-IF
*
* actualizamos puntero de lectura y flag de fin
IF NOT EOF FDESC AND FIN NE 4
* si es un final de registro natural, seguimos leyendo por el
* siguiente en orden de continuación de por donde íbamos…
IF FIN = 3
W-LINEA = ”
MOVE REG-LINEA TO W-LINEA
WS-CONT = WS-CONT – 30180
* si al final hubo una lectura malformed, … reiniciamos
* contadores.
ELSE
DISPLAY ‘ MALFORMED !! ‘ WS-CONT
DISPLAY ‘ MALFORMED !! ‘ W-CHAR(WS-CONT)
*
WS-CONT = WS-CONT – 2
WS-CONT-OUT = WS-CONT-OUT – 1
DISPLAY ‘ NEW_POS = ‘ WS-CONT
DISPLAY ‘ NEW_VALOR <= ' W-CHAR(WS-CONT)
W-CHAR-OUT(WS-CONT-OUT) = W-CHAR(WS-CONT)
WS-CONT-OUT = WS-CONT-OUT + 1
WS-CONT = WS-CONT + 1
WS-SALTO = W-CHAR-N(WS-CONT)
DISPLAY ‘ SALTO = ‘ WS-SALTO
WS-CONT = WS-CONT + WS-SALTO + 1
DISPLAY ‘ NEW = ‘ W-CHAR(WS-CONT)
END-IF
*
IF FIN < 4
FIN = 0
END-IF
END-IF
END-IF
END-DO
END-IF
STOP.
*——————————————————————–
ESTADISTICAS. PROC
*——————————————————————–
DISPLAY ‘*—————————————————–*’
DISPLAY ‘*—- PROGRAMA AJP8040 – *’
DISPLAY ‘*—————————————————–*’
DISPLAY ‘* FICHERO ENTRADA …………..:’ FDESC:RECORD-COUNT
DISPLAY ‘* FICHERO SALIDA …………..:’ FSAL:RECORD-COUNT
DISPLAY ‘*—————————————————–*’
END-PROC.
 
 
 
En breve añadiré otros post sobre otros métodos de cifrado mucho más complejos, aunque como se ha podido observar, no hace falta inventar protocolos muy complicados para dejar un texto ilegible al ojo humano. De hecho, el resultado parece un contenido binario puro.
 
Ejemplo-1 (cifrado con el GrimmXtract)


 
NOTA: por cierto, el nombre de Extracción Grimm lo ideé en honor a la multitud de cuentos de los hermanos Grimm, donde los niños recuperaban el camino andado gracias a que iban recogiendo las “semillas” de pan que habían ido dejando. En cierto modo, este procedimiento es lo mismo.
 
Un Saludo y a disfrutar.


Acciones

Information

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s




A %d blogueros les gusta esto: