TARDÍGRADOS

Ciencia en español -ʟᴀ ʀᴀᴢóɴ ᴇsᴛá ᴀʜí ғᴜᴇʀᴀ-

Archive for May, 2020

Criptografía: un programilla muy sencillo más para codificar cadenas

Posted by Albert Zotkin on May 31, 2020

Hace ya algunos años, escribí y compilé un pequeño programa en lenguaje C para encriptar archivos. Era simple y directo. Ahora, lo he rescatado y lo he traducido a lenguaje javascript para node.js. Y aquí te lo presento:

/*
 ESTE PEQUEÑO PROGRAMILLA HACE LO SIGUIENTE:
 			1. DIVIDE LA CADENA DE BYTES EN DOS MITADES. DESPOUES, 
 			2. TRASPONE EL BYTE DE LA POSICIÓN X A LA POSICIÓN 
 				 L - X, DONDE L ES LA LONGITUD DE LA CADENA. Y SEGUIDAMENTE 
 				 
 			3. RESTA(Ó SUMA, DEPENDIENDO DE SI EL PARÁMETRO MODO ES 1 Ó 0) 
 				 AL CÓDIGO ASCII DE CADA BYTE.
*/

const fs = require('fs');
var file1 = '../uploads/building.jpg';
var file2 = '../uploads/building-2.jpg';
var flujofichero = fs.readFileSync(file1);
var puntero = 0;
var modo = 1;
var size = flujofichero.length;

if(flujofichero.length){
 while(puntero < size/2)
  {
    Traspuesta(puntero,size-puntero-1,modo,flujofichero);
    puntero++;   
  }
 
  fs.writeFile(file2, flujofichero, 'binary', function(err){ 	
  });
}




function Traspuesta(i, j, modo, buffer){ 

  var nparam1,nparam2;
  nparam1 = buffer.readUInt8(i);
  if(modo)nparam1 = nparam1 - 10;
  else nparam1 = nparam1 + 10;
  nparam1 = nparam1<0?256+nparam1:nparam1;
	nparam1 = nparam1>0xff?nparam1-256:nparam1;
  nparam2 = buffer.readUInt8(j);//flujofichero.charCodeAt(j);
  if(modo)nparam2 = nparam2 - 10;
  else nparam2 = nparam2 + 10;
 
  nparam2 = nparam2<0?256+nparam2:nparam2;
	nparam2 = nparam2>0xff?nparam2-256:nparam2;
  buffer.writeUInt8(nparam2, i);
  buffer.writeUInt8(nparam1, j);
}

En el código de arriba elijo un archivo de una imagen jpg llamado building.jpg. Lo abro mediante la instrucción flujofichero = fs.readFileSync(file1);, con lo cual sus bytes quedan cargados en la variable flujofichero , que es un buffer. Conprobamos que dicho buffer tiene longitud no nula, antes de aplicarle el proceso de encriptación. Resulta que nuestro archivo imagen posee una longitud en bytes de flujofichero.length = 699.395 bytes.
Ahora ya podemos empezar a encriptar. Aplicamos la función Traspuesta a lo largo de la cadena de bytes, y eso lo hacemos mediante un loop while, con la condición de que salga del bucle cuando la variable puntero sea igual o mayor a la mitad de la longitud de la cadena de bytes. La función Traspuesta es muy sencilla, el único misterio está en cono se puede truncar cada bytes al restarle o sumarle 10. Cuando a 1 byte, cuyo valor sabemos que está en el intervalo [0,255], porque 1 byte son 8 bits, le sumamos un número tal que el resultado desbordaría esos 8 bits, es decier se necesitarían más bits para expresar el resultado, entonces se produce un truncamiento. Pero ese truncamiento del byte Javascript no es posible porque las variables de javascript no poseen esa pre-condición. Por lo tanto, el truncamiento del byte hay que hacerlo manualmente. ¿Cómo?. Muy sencillo. Supongamos que tenemos el byte almacenado en la variable nparam1 y al sumarle 10 se desborda, entonces le aplicamos la siguiente condición, en caso de que se produzca ese desbordamiento:

nparam1 = nparam1>0xff?nparam1-256:nparam1;

que viene a decir que en caso de que la variable nparam1 sea mayor a 255, entonces quede truncada a nparam1-256. Algo muy parecido hacemos para el caso en que la variable sea un número negativo

 nparam1 = nparam1<0?256+nparam1:nparam1;
De esta forma el byte queda truncado, siempre tendremos 8 bits, y por lo tanto el tamaño del archivo encriptado será el mismo que el del original. Estos truncamientos se pueden hacer de muchas formas, yo he elegido la más “literaria”. El resultado de encriptar lo guardamos en otro archivo nuevo llamado building-2.jpg, y eso lo hacemos mediante la función asincrónica

 fs.writeFile(file2, flujofichero, 'binary', function(err)
{if(err)throw err;});

Otra cosa interesante de este programilla de encriptar es el parámetro modo. Si encriptas en modo = 1, entonces para recuperar el archivo original debes aplicar una encriptación sobre el archivo encriptado, pero con modo = 0. y viceversa. Si aplicas sucesivas iteraciones con el mismo modo, solo al cabo de 128 iteraciones consigues llegar al archivo original.
Veamos el aspecto de los dos archivos, el original y el encriptado:
y los primeros bytes de esa imagen original son estos:

00000000h: FF D8 FF E0 00 10 4A 46 49 46 00 01 02 01 00 48 ; ÿØÿà..JFIF.....H
00000010h: 00 48 00 00 FF E1 29 8A 45 78 69 66 00 00 4D 4D ; .H..ÿá)ŠExif..MM
00000020h: 00 2A 00 00 00 08 00 07 01 12 00 03 00 00 00 01 ; .*..............
00000030h: 00 01 00 00 01 1A 00 05 00 00 00 01 00 00 00 62 ; ...............b
00000040h: 01 1B 00 05 00 00 00 01 00 00 00 6A 01 28 00 03 ; ...........j.(..
00000050h: 00 00 00 01 00 02 00 00 01 31 00 02 00 00 00 1C ; .........1......
00000060h: 00 00 00 72 01 32 00 02 00 00 00 14 00 00 00 8E ; ...r.2.........Ž
00000070h: 87 69 00 04 00 00 00 01 00 00 00 A4 00 00 00 D0 ; ‡i.........¤...Ð
00000080h: 00 0A FC 80 00 00 27 10 00 0A FC 80 00 00 27 10 ; ..ü€..'...ü€..'.
00000090h: 41 64 6F 62 65 20 50 68 6F 74 6F 73 68 6F 70 20 ; Adobe Photoshop 
000000a0h: 43 53 34 20 57 69 6E 64 6F 77 73 00 32 30 31 37 ; CS4 Windows.2017
000000b0h: 3A 30 33 3A 30 31 20 32 32 3A 32 38 3A 32 32 00 ; :03:01 22:28:22.
000000c0h: 00 00 00 03 A0 01 00 03 00 00 00 01 00 01 00 00 ; .... ...........
000000d0h: A0 02 00 04 00 00 00 01 00 00 03 69 A0 03 00 04 ;  ..........i ...
000000e0h: 00 00 00 01 00 00 02 D9 00 00 00 00 00 00 00 06 ; .......Ù........
000000f0h: 01 03 00 03 00 00 00 01 00 06 00 00 01 1A 00 05 ; ................
00000100h: 00 00 00 01 00 00 01 1E 01 1B 00 05 00 00 00 01 ; ................

L Y los primeros bytes del archivo encriptado en mod = 0, son estos:

00000000h: E3 09 49 F5 89 8D 3B 06 D1 0F 94 0A 09 F9 F4 29 ; ã.Iõ‰;.Ñ.”..ùô)
00000010h: C1 FC C9 6E AA 02 C9 9C F5 11 4D 02 E9 94 1D 0A ; ÁüÉnª.Éœõ.M.é”..
00000020h: 09 E9 62 71 90 FC A9 EB E0 0A 09 AD D8 55 D4 0A ; .ébqü©ëà..­ØUÔ.
00000030h: 09 5C CE 89 DC 7F 19 06 61 43 98 0A 09 48 B8 81 ; .\ΉÜ..aC˜..H¸
00000040h: 06 D3 89 61 00 81 62 A1 3F EA 0A 09 E9 05 A1 7B ; .Ó‰a.b¡?ê..é.¡{
00000050h: 27 01 CC 0A 09 FC 04 49 B4 95 0F 0A 09 75 EB 05 ; '.Ì..ü.I´•...uë.
00000060h: C9 62 39 FC BD 0A 09 45 70 07 19 F4 1A A1 07 E9 ; Éb9ü½..Ep..ô.¡.é
00000070h: 3A 21 0A 09 87 7F 2B 19 02 C9 EE 35 08 2D B6 A9 ; :!..‡+..Éî5.-¶©
00000080h: 28 FC E9 EF 35 08 41 87 C2 D3 0A 09 9F 8F 02 0A ; (üéï5.A‡ÂÓ..Ÿ..
00000090h: 09 BC 78 44 06 79 ED 07 95 F4 30 9B 0A 09 62 98 ; .¼xD.yí.•ô0›..b˜
000000a0h: F7 0A 09 AE D8 B4 EB C9 FB C6 89 9F 7F A3 5F 03 ; ÷..®Ø´ëÉûƉŸ£_.
000000b0h: 39 D2 02 59 B4 95 11 0A 09 67 C5 07 D9 7E 6B CD ; 9Ò.Y´•...gÅ.Ù~kÍ
000000c0h: 0A 09 D5 A1 02 89 B8 98 1E 02 29 62 CE 0A 09 63 ; ..Õ¡.‰¸˜..)bÎ..c
000000d0h: 47 B2 4E 0A 09 19 7F F9 89 B3 19 E6 D3 0A 09 5C ; G²N...ù‰³.æÓ..\
000000e0h: 02 08 7B E0 65 13 08 B9 03 96 0A 09 BE C4 94 C1 ; ..{àe..¹.–..¾Ä”Á
000000f0h: FC C9 BF E5 0A 09 11 F5 D6 5F 08 ED DC 01 79 BD ; üÉ¿å...õÖ_.íÜ.y½
00000100h: 18 D6 08 39 3F F9 C9 B2 FD C8 01 89 FA 08 65 E0 ; .Ö.9?ùɲýÈ.‰ú.eà

Como me pareció un script muy sencillo y útil, lo he incluido como función dentro de mi libreria de utilidades de node.js, para cuando necesite una sencilla e inmediata encriptación de algo.

'use strict';
const OUTPUT = 1;
const INPUT = 0;
function WM_Encrypt(buffer, mode){
		 if(buffer.length){
				var puntero = 0;
				var size = buffer.length;
 				while(puntero < size/2)
  					{
    					Traspuesta(puntero,size-puntero-1,mode,buffer);
    					puntero++;   
  					}
		}
		
		return buffer;
}
function Traspuesta(i, j, modo, buffer){ 

  var nparam1,nparam2;
  nparam1 = buffer.readUInt8(i);
  if(modo)nparam1 = nparam1 - 10;
  else nparam1 = nparam1 + 10;
  nparam1 = nparam1<0?256+nparam1:nparam1;
	nparam1 = nparam1>0xff?nparam1-256:nparam1;
  nparam2 = buffer.readUInt8(j);//flujofichero.charCodeAt(j);
  if(modo)nparam2 = nparam2 - 10;
  else nparam2 = nparam2 + 10;
 
  nparam2 = nparam2<0?256+nparam2:nparam2;
	nparam2 = nparam2>0xff?nparam2-256:nparam2;
  buffer.writeUInt8(nparam2, i);
  buffer.writeUInt8(nparam1, j);
}

function wm_encode(buffer){
	return WM_Encrypt(buffer, OUTPUT);
}
function wm_decode(buffer){
	return WM_Encrypt(buffer, INPUT);
}
module.exports =
{
	WM_Encrypt:WM_Encrypt,
	wm_encode:wm_encode,
	wm_decode:wm_decode
};

Así, os puedo decir que:

#0ieZejW&eZecd[ieZWjf_hYd[ieZkbWI

que al desencriptarlo en modo 1, ya que fue encriptado en modo 0, obtenemos la cadena:

Saludos encriptados en modo 0 a todos 🙂

Posted in criptografía, informática, Matemáticas | Tagged: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a Comment »