Archivo de la categoría: Geek

10 things you should be doing if you care about security in your Tech Startup

I’ve been working in the startup world as a Software Engineer for a little bit more than two years now, as most of you already know, I’m very passionate about information security so I decided to create a list of things you can do to protect your technology Startup (most of them for free).

SPOILER ALERT: This publication is not going to be your typical article about which crypto cipher is better to use, IDS comparisons or talking about specific DLP products , instead, I would like to cover 10 actions (more like advices) you can take if you value your product, your data, your employees and if you want to protect your Startup in general.

So if you are the CEO, CTO, some high executive or a decision maker in your Startup this information is for you.

1: Enforce the use of password managers

Everything starts with a password, literally, sign-in into your computer is one of the first thing most of you do every morning. Whether email clients, social networks, instant messaging apps, or online banking all this requires the user to provide a password in order to access the service so it’s natural for common users to want to think in a password only 1 time and then reuse it across multiple services.

Reusing passwords (even with small variations) it’s a bad thing because once your password is guessed/stolen it can be used to compromise all your other accounts (facebook, twitter, instagram, gmail, outlook, etc), attackers can automate the process using hacking tools such as credmap: The Credential Mapper.

So how do we prevent employees passwords to be guessed (dictionary attack) while at the same time make sure they are using strong and unique passwords on each one of their accounts? The answer is Password Managers.

Password Managers allow you to have one master password (for choosing a strong master password please refer to my talk How to create secure passwords) and then generate all the others you need based on a secure configuration such as secret length, character types, etc.

So the next time you want to access your favorite social network you just need to copy and paste the password, that also prevents your password for being stolen in case of a keylogger attack. You don’t want your community manager accounts to be stolen right?

There are a lot of good solutions out there for managing your passwords, some of them are free and open-source and some others requires you to buy a license, I personally use KeePass which is free, here is a list of the most popular password managers, doesn’t matter which one you want to choose but go ahead and start using password managers if you are not doing it yet!

2: Use multi-factor authentication if possible

The key of security is to add multiple layers of protection so in case one of them fails the other ones handle the risk, in particular for protecting accounts we can suggest our employees to use 2 factor or multi-factor authentication every time they can, so if a data breach happen and the passwords are stolen and cracked, attackers are still unable to log into the accounts because they are missing the token generator.

Now a days most of the more popular services support multi-factor authentication using one time passwords, token generators (such as google authenticator) or even hardware authenticator devices.

Personally I use a Yubico authenticator key and I’m very happy with it 🙂 every time I need to access my accounts from a new IP address or an unrecognized browser, websites such as Facebook or Gmail will ask for my authentication key, that’s very helpful because even if my password is leaked/cracked or someone guess it, they still need the physical key to access the service. 

If you don’t have a budget or prefer not to spend money on this you still can enforce multi-factor authentication using these free apps (every employee can have a token generator right on his smartphone):

3: Choose a secure instant messaging application

Every organization use some kind of real time communication application (Slack, Microsoft Teams, etc) and sometimes employees need to share sensitive information between them, they do not realize the information is also being shared with the third-party service provider who can read it.

Fortunately, nowadays more and more services support security features such as end to end encryption which means all communications between devices are encrypted (each device has a public and a private key) and not even the service provider can read them because they don’t have the private keys.

Another cool feature is self-destruct messages, basically you can set a timer so messages only exists during a particular amount of time after being send and then are destroyed, very useful when you want to share sensitive data such as passwords.

Some free apps that include these features are:

4: Securing all Email communications

Email communications is an essential part in every organization, making it a very attractive vector for attackers, according to a new report from PhishMe, 91% of Cyberattacks start with a phishing email, so even if you have advanced network controls, deceiving your users is still easy.

Nowadays attackers have access to sophisticated phishing tools like SET (Social-Engineer Toolkit) or Gophish which they use to target your employees, they also have access to large repositories of open-source phishing tools they use to tune and adapt their attacks to specific people.

Most of this tools allow attackers to spoof corporate emails and trick your users into downloading malicious files into their systems and into your network, spotting spoofed email addresses is very difficult for common users however using security software like PGP (Pretty Good Privacy) & GPG can help you to mitigate the issue.

Enforcing the use of software such as GPG (GNU Privacy Guard) could help your startup in many ways, like verify the legitimacy of a received messages or encrypt an email content so only a specific user can read them.

You can verify if a message you receive is legit by using the public key of the sender (usually another employee in the organization), meaning: if the person that sent you the email also signed the message using his private key and that private key is associated with the public key you have, then you are guaranteed the message is coming from the right person.

I know this sounds a little bit confusing at the beginning, but the main idea is that every person in the company has a key pair, a public key and a private key, everybody exchanges their public keys while keep their private keys to themself, so when I want to send a message to Mr John Doe I write the message normally and then I proceed to sign it with my own secret key, optionally I can encrypt the message using the public key of John Doe, so the message can only be decrypted and read it by the private/secret key of John, finally John can use my public key to verify the signature I applied to the original message (the one I generated with my private key).

If you still don’t get it don’t worry about it, nowadays most email clients support PGP and the process for verifying and decrypting emails is automatically, there is also a chrome extension called FlowCrypt that I highly recommend!

This message was encrypted with my public key and then sent to me, not even google can read this.
The message decrypted on my browser via the FlowCrypt browser extension

5: Encrypting all your drives

Now we are introducing the concept endpoint protection and “data loss prevention“, in fact I think most of you already use some form of data encryption software, I’m not going to go deep into the details but encrypting your drives could protect your data in many cases, ie: someone steal a company hard drive and try to mount it in another computer to read the information.

If your employees are MacOS users, the operating system already come shipped with FileVault enabled by default, if they use Windows they can use BitLocker and if they use a modern Linux distribution (ie: Ubuntu) full disk encryption is also available.

Data encryption has pros and cons, but the benefits are superior from a privacy and security stand point so I highly recommend to use full disk encryption in all company devices if possible, also the solutions I mentioned above are all free, so you don’t need to spend any money on this one too in order to protect your employees.

6: Encourage secure coding best practices

Usually, when you start a new company then financial resources are limited and you need to be very careful with the people you hire, basically you want to have the best developers, people that are really good at whatever they do but also are wiling to learn and adapt to different situations, you want Rockstar developers.

Rockstars developers have the potential for learning anything, so feed them with the right content, Open Security Training contains great resources about different topics of security like Introduction to Secure Coding, the best part is, are you ready?, its all FREE! in fact this is how I have been learning about security all this years.

Besides Open Security Training there is also The Open Web Application Security Project (OWASP), which is also a good resource for starters so they can learn how to create secure web applications and also secure mobile apps.

Everybody can learn about Security these days, encourage your developers to do it (give them time and resources) and your team will become stronger!, here are some extra sources I had used in the past:

7: Consider hiring a security expert to join your team or an external security team

This advice is more for mature startups or executives who already have a budget to spend on cybersecurity, but it can also apply if you are a small startup and have some friends in the security community.

The idea is to have someone in your team that can give you advice and guidance on different security matters, ie: implementing a security plan for the software development process, do threat modeling in your organization, security infrastructure (IDS, IPS, firewalls, etc), security training, network protection or just make sure your employees are safe are just some examples of things your tech Startup needs from a security perspective.

Besides having your own security guy consider hiring an external security team too, having the security assessment of an external team allow you to simulate more realistic attacks to your organization so you can be more prepared when the real thing happen.

Here are some personal thoughts about security people:

  • Security people are different
  • We enjoy talking about security all the time
  • We want to get asked about how to protect X or Y technology
  • We enjoy challenges and puzzles
  • we enjoy to break stuff and tell you how to fix them.

8: Start a bug bounty program

Companies doesn’t like the idea of their product being hacked, personally I believe that way of thinking need to change because it’s a good thing to have a group of white hat hackers finding vulnerabilities in your software before the bad guys do it.

You can start a bug bounty program with a well defined scope so people can try to hack your product legally (you can even set some special environments for this), there are some guidelines regarding how much to pay depending on the type of vulnerability but if you are still a small startup you can also offer some “swag” like t-shirts or gadgets.

In return you get (most of the time) an army of high quality security researchers that will deliver good vulnerability reports, including how to fix your security issues, everybody wins 🙂

Some popular bug bounty platforms right now are:

9: Encourage a cybersecurity culture in the Startup

The success of the cybersecurity strategy in the organization depends pretty much on the people, you can not just spend a lot of money on security assets like Firewalls and Antivirus and expect everything to be magically safe, it’s not possible because people are always the weakest part in the chain. Security is like a game and everybody need to play including high executives like CEOs and CTOs.

In order to have a culture of cybersecurity organizations have tried different things through the years, even punishing their employees, which is not very effective because people end hating security policies. In general people tend to care about security only when affects them directly but they also like rewards so there is a “new” trend in the security community about using gamification in which basically you reward your employees when they have a responsible security behaviour.

Those action might include:

  • Employees getting rewards when reporting phishing emails
  • Escort people without badge outside the facilities
  • Report suspicious USB drives or hardware that should not be there to the IT/Security department.
  • Enforce people to lock their workstation when not using them by sending emails (using the unlocked account) about free donuts for the whole floor/department/team :p

The idea of all this is to be fun while at the same time the organization become more secure against external threats.

10: Be transparent about Security issues and data breaches

Your biggest fear became true, your Startup got hacked and your information is all over the Internet, If you followed all my advices chances are your sensitive information like passwords are encrypted, which is useless for the attackers, however you still have a moral (and in some places legal) duty, you need to notify your customers and employees about the data breach (according to GDPR you have 72 hours to report a personal data breach after it’s discovered) basically every minute you wait is a minute attackers can invest into cracking and recovering the information so it’s better to communicate the incident, so people can start acting accordingly (change passwords, cancel credit cards, etc).

If you decide to hide the breach and continue without doing anything eventually everybody is going to know about hack and your reputation will be irreversibly damaged (nobody will trust you anymore) so its better to be open with your customers an accept the failure, the shame will be momentary but you will do the right thing.

There is no such thing as a Silver bullet in Cybersecurity, It’s not a matter of if you are going to be hacked or not, it’s about when is going to happen and if your organization is going to be prepared, and this is true for all companies.

Some final thoughts

Security people are often seen as blockers in the organization but I assure you, they have good intentions so please listen to them. Security is hard to implement and even harder to maintain so if you are the CEO/CTO/[Person with authority] of the startup consider to join the security team so you can experience first hand the whole process 🙂

Finally, all these advices are based on my personal opinion (I’m just a security enthusiast) so if you think I should add something else please leave it in the comments.

Happy hacking 🙂

#DailyCodingProblem: El producto de todos los elementos en el arreglo menos el elemento actual

https://www.dailycodingproblem.com/

Good morning! Here’s your coding interview problem for today.

This problem was asked by Uber.

Given an array of integers, return a new array such that each element at index i of the new array is the product of all the numbers in the original array except the one at i.

For example, if our input was [1, 2, 3, 4, 5], the expected output would be [120, 60, 40, 30, 24]. If our input was [3, 2, 1], the expected output would be [2, 3, 6].

Follow-up: what if you can’t use division?

Si ignoramos la restricción este problema es muy sencillo de resolver.

  • Iteramos el arreglo y calculamos el producto total de todos los elementos: 1 x 2 x 3 x 4 x 5 = 120
  • Iteramos nuevamente dividiendo el total entre cada uno de los elementos y guardamos esos resultados en nuevo arreglo: 120/1, 120/2, 120/3, 120/4, 120/5

La complejidad de esta solución seria O(2n) o simplemente O(n), pero debido a que el problema dice que no podemos usar la división las cosas se complican un poco mas.

Solución cuadrática

Sin usar la división la solución mas obvia es una solución cuadrática, iteramos el arreglo y por cada elemento vamos a ir acumulando el producto de esos valores menos el elemento i actual.

    int[] calculateProduct(int[] numbers) {
        int[] result = new int[numbers.length];
        // ...
        // ... logica para inicializar todos los valores de result en 1
        // ...
        for (int i = 0; i < numbers.length; i += 1) {
            for (int j = 0; j < numbers.length; j += 1) {
                if (i != j) {
                    result[j] *= numbers[i];
                }
            }
        }
        return result;
    }

Esta solución es muy fácil de entender pero no es para nada eficiente, O(n2), en la publicación anterior ya analizábamos otra solución cuadrática y veíamos que era un problema con inputs de datos muy grandes, por ejemplo un arreglo de 1000 elementos (1 millón de operaciones).

Solución en tiempo lineal con programación dinámica

Después de pensar un rato en este problema, haciendo algunas anotaciones y viendo la relación entre los indices y el producto parcial de cada uno de ellos llegue a la siguiente solución.

La primera fila son los valores del arreglo, después como si estuviéramos iterando, el valor actual es marcado en color amarillo, si pudiéramos obtener el producto acumulado de izquierda y derecha de cada uno de los elementos entonces podríamos resolver el problema multiplicándolos entre si 🙂

Ejemplo: para el obtener el resultado del 3 tendríamos que multiplicar sus valores de la izquierda que son 2 y sus valores de la derecha que son 20 dando como resultado 40.

Vamos a recorrer el arreglo por la izquierda y por la derecha guardando el producto de sus elementos, para eso necesitaremos 2 arreglos mas, left y right, podemos hacer esos recorridos en una sola iteración, después iteramos nuevamente multiplicando los valores de izquierdo y derecho de result[i].

    public static int[] calculateProduct(int[] numbers) {
        int[] result = new int[numbers.length];
        int[] left = new int[numbers.length];
        int[] right = new int[numbers.length];
        int totalLeft = 1;
        int totalRight = 1;
        int size = numbers.length - 1;
        for (int i = 0; i <= size; i += 1) {
            totalLeft *= numbers[i];
            totalRight *= numbers[size - i];
            left[i] = totalLeft;
            right[size - i] = totalRight;

        }
        for (int i = 0; i < numbers.length; i += 1) {
            if (i == 0) {
                result[i] = right[i + 1];
            } else if (i == numbers.length - 1) {
                result[i] = left[i - 1];
            } else {
                result[i] = left[i - 1] * right[i + 1];
            }
        }
        return result;
    }

La complejidad en tiempo de esta solución es O(2n) o O(n).
La complejidad en espacio de esta solución es O(3n) o O(n), (tomando en cuenta solamente los 3 nuevos arreglos que necesitamos, todas las demás variables son espacio constante).

Happy hacking 🙂

#DailyCodingProblem: Encontrar si dos números dentro de un arreglo suman K

https://www.dailycodingproblem.com/

Good morning! Here’s your coding interview problem for today.

This problem was recently asked by Google.

Given a list of numbers and a number k, return whether any two numbers from the list add up to k.

For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17.

Bonus: Can you do this in one pass?

Como el problema lo indica, debemos crear una función que reciba 2 parámetros, un arreglo de números y un numero entero k, debemos buscar dentro de ese arreglo si dos elementos sumados entre si son iguales al numero k.

La solución naive para este problema seria iterar sobre los elementos del arreglo y por cada uno de ellos iterar nuevamente para ver si la suma de numbers[i] + numbers[j] da como resultado el numero k

   for (int i = 0; i < numbers.length; i += 1) {
        for (int j = 0; j < numbers.length; j += 1) {
            // evitamos la comparación de un elemento consigo mismo
            if (i != j && (numbers[i] + numbers[j]) == k) {
                return true;
            }
        }
    }

Esta solución no es muy buena ya que por cada elemento en el arreglo vamos a iterar nuevamente los datos, resultando en una complejidad O(n2) donde n es el tamaño del arreglo, imagina un arreglo de 1000 elementos, tendríamos que realizar 1 millón de operaciones.

Solución lineal para encontrar si dos números suman K

Vamos a iterar el arreglo, pero esta vez vamos a usar un HashSet para guardar información, por cada elemento:

  • Calculamos el numero que falta para completar el total k
  • Revisamos si el numero que nos falta existe en el HashSet, si es así devolvemos true (buscar elementos en un HashSet se hace en tiempo constante)
  • Si el numero que buscamos no existe entonces registramos el numero actual como “observado” en el HashSet

Si terminamos de recorrer el arreglo significa que no hay números que sumados nos den como resultado k y por lo tanto devolvemos false.

    public static boolean findSum(int[] numbers, int k) {
        HashSet<Integer> seenNumbers = new HashSet<>();
        for (int i = 0; i < numbers.length; i += 1) {
            int missing = k - numbers[i];
            if (seenNumbers.contains(missing)) {
                return true;
            }
            seenNumbers.add(numbers[i]);
        }
        return false;
    }

La complejidad en tiempo de esta solución es O(n), ya que el numero de operaciones a realizar depende directamente del tamaño del arreglo n.

La complejidad en espacio de esta solución también es O(n), el espacio o la memoria a utilizar depende directamente de lo que reciba la función, en este caso un arreglo de n elementos, utilizamos un HashSet para almacenar máximo el mismo numero de elementos y no realizamos otras operaciones que sean significativas con la memoria.

Happy hacking 🙂

Security Fest #CTF – Zion write up

Para este reto nos daban un archivo comprimido zion.tar.gz, procedemos a descomprimirlo y obtenemos otro archivo llamado YouKnow.

El archivo no tiene extension pero utilizamos el comando file para ver que tipo de archivo es.

Parece un archivo de Microsoft Word Office y sabemos que los archivos docx en realidad son archivos en formato zip.

Procedemos a descomprimir YouKnow

Obtenemos varios archivos y carpetas, comenzamos a analizarlos de uno por uno, sin embargo no encontramos nada que haga referencia a la bandera del reto. (analice la imagen del conejo con un par de herramientas de esteganografía pero no había nada)

Damos un paso atrás y abrimos el archivo YouKnow en un editor hexadecimal de su elección, you utilice Sublime

Observamos la cabecera estándar PK del formato ZIP

Al ir analizando el archivo, hacia el final, algo salta inmediatamente a la vista.

Parece que hay otro archivo Zip concatenado al primero pero los bytes están en orden inverso (observen como el archivo termina en KP, y vemos algunos strings como lmx que seria xml).

Podemos utilizar python para invertir los bytes del archivo fácilmente.

open('YouKnow_reversed','wb').write(open('YouKnow','rb').read()[::-1])

Obtenemos el archivo con los bytes invertidos y procedemos a descomprimirlo.

Obtenemos nuevamente varios archivos y carpetas.

Y en donde estaba la imagen anterior del conejo rojo ahora encontramos otra imagen, esta vez de un conejo azul que nos muestra la bandera del reto 🙂

La bandera del reto es sctf{m41nfr4m3_4cc3ss_c0d3_1337_4lw4s}

Bonus

Programe una pequeña herramienta en python llamada reverse bytes para invertir los bytes de un archivo utilizando una cli mas amigable.

usage: rbytes.py [-h] [-o OUTFILE] infile

A simple python script for reverse the bytes of a file.

Author: Lenin Alevski Huerta Arias
Year: 2018

positional arguments:
  infile                Input file

optional arguments:
  -h, --help            show this help message and exit
  -o OUTFILE, --outfile OUTFILE
                        Output file

Happy hacking 🙂

Implementación teórica con BlockChain para un sistema de votaciones

Ha inicios de este año recibí un mensaje en Linkedin donde me preguntaban si estaba interesado en comenzar un proceso de reclutamiento, lo cual no es nada raro ya que siendo ingeniero de software (una de las industrias con más de profesionales en la actualidad) te llegan correos con propuestas laborales todos los días, sin embargo esta propuesta me pareció bastante interesante ya que necesitaban un Senior BlockChain Engineer, el mensaje en cuestión era:

Si bien no tengo experiencia desarrollando BlockChain como tal, si tengo bastante experiencia con sistemas distribuidos, así que me di a la tarea de comenzar a aprender el funcionamiento de esta tecnología desde un punto de vista técnico, sus conceptos básicos y sobre todo tratar de entender por que se volvió tan popular y sera el “futuro”.

Disclaimer: El código mostrado en el articulo a continuación no es una implementación real de BlockChain (no esta ni cerca del 1% de ser un proyecto real) la intención es resaltar y explicar las partes mas importantes y hacer hincapié en los conceptos básicos de lo que es BlockChain, el código dista de ser perfecto y no debe ser usado en producción.

Bueno ya estan advertidos hehe, comenzamos.

El bloque

Para entender lo que es la cadena de bloques primero tenemos que entender lo que es un bloque, el bloque puede ser representado como un objeto que contiene un identificador único, un timestamp, información en cualquier formato que queramos, un hash o checksum que representa la información que contiene y lo mas importante es que debe tener una referencia al bloque anterior, como si de una lista enlazada se tratara.

Con un lenguaje tan sencillo como Javascript podemos representar al bloque de la siguiente forma:

class Block {
  constructor(index, timestamp, data, previousHash = '') {
    this.index = index;
    this.timestamp = timestamp;
    this.data = data;
    this.previousHash = previousHash;
    this.hash = this.calculateHash();
  }

  calculateHash() {
    return SHA256(this.index + this.timestamp + JSON.stringify(this.data) + this.previousHash).toString();
  }
}

La clase bloque contiene una función muy especial llamada calculateHash, esta función toma toda la información del bloque (index, timestamp, data, previousHash), la concatena y le aplica un algoritmo de hashing para generar un checkSum que despues sera almacenado en el mismo bloque, la parte interesante y una de las razones por las que BlockChain es seguro es precisamente el uso de estas funciones criptográficas, ya que su integridad esta respaldada de forma matemáticamente.

Detengamonos por unos segundos y pensemos, si todo bloque debe de tener una referencia al hash del bloque anterior, y ese dato (previousHash) se utiliza para calcular el hash del bloque actual eso significa que si alguien hackea/modifica/elimina uno de los bloques anteriores todos los siguientes bloques quedarían invalidados 🙂 , seria un efecto domino de fallas en la integridad de los bloques.

Esta es la representación mas básica que se me ocurre de un bloque, en la vida real son estructuras de datos mucho mas complejas y en la parte de los datos pueden contener muchísimas mas piezas de información y no solo una, como lo es el caso de las transacciones en la BlockChain de Bitcoin.

La cadena

Habiendo entendido un poco lo que es el bloque ahora toca el turno de la cadena, esta es otra estructura de datos que funciona alrededor de los bloques y realiza operaciones con ellos, mencione que esta tecnología es muy parecida a una lista enlazada, si el bloque es uno de los nodos entonces la cadena serian las operaciones de agregar, eliminar, modificar, etc nodos, aunque en BlockChain solo podemos agregar bloques y nunca eliminarlos por lo que mencionaba sobre la integridad de los hashes.

En Javascript podemos representar la cadena de la siguiente forma:

class BlockChain {
  constructor() {
    this.chain = [this.createGenesisBlock()];
  }

  createGenesisBlock() {
    return new Block(0, new Date(), "Genesis block");
  }

  getLatestBlock() {
    return this.chain[this.chain.length - 1];
  }

  addBlock(block) {
    block.previousHash = this.getLatestBlock().hash;
    block.hash = block.calculateHash();
    this.chain.push(block);
  }

  isChainValid() {
    for(let i = 1; i < this.chain.length; i++) {
      const currentBlock = this.chain[i];
      const previousBlock = this.chain[i - 1];
      if (currentBlock.hash !== currentBlock.calculateHash()) {
        return false;
      }
      if(currentBlock.previousHash !== previousBlock.hash) {
        return false;
      } 
    }
    return true;
  }
}

Tenemos varias funciones interesantes como addBlock (agregar nuevo bloque), getLatestBlock (obtener el ultimo bloque), isChainValid (valida la integridad de la cadena de bloques) y createGenesisBlock, estas dos ultimas son las mas interesantes.

Mencione que cada bloque debe tener una referencia al bloque anterior ¿Pero entonces cuál fue el primer bloque 🙂 ?

Toda cadena de bloques inicia con un bloque llamado Bloque Genesis, ese nombre no es nada mas que una convención, es la forma de inicializar la cadena.

La función isChainValid verifica la integridad de la cadena utilizando los hashes de cada uno de los bloques, comienza revisando a partir del segundo bloque (uno después del bloque génesis) y primero revisa que el hash actual efectivamente corresponda con la información del bloque

if (currentBlock.hash !== currentBlock.calculateHash()) {
  return false;
}

Después revisa que la referencia (previousHash) al bloque anterior sea la correcta:

if(currentBlock.previousHash !== previousBlock.hash) {
  return false;
} 

Así hasta llegar al ultimo bloque y si todo sale bien la cadena es valida :). Sin embargo si entendieron bien el concepto de verificación de integridad pueden ver el problema con esta implementación, si bien no es posible modificar la información de un bloque intermedio, teóricamente es posible “hackear” la información del ultimo bloque antes de que agreguen nuevos nodos a la cadena.

Este precisamente es el problema que se aborda en el primer paper de Bitcoin por Satoshi Nakamoto: Bitcoin: A Peer-to-Peer Electronic Cash System

Sin entrar en detalles, en implementaciones reales la cadena de bloques no se encuentra centralizada en una sola maquina, en lugar de eso es una red distribuida y todas las computadoras de la red contienen una copia completa de la cadena, entonces cada vez que alguien va a agregar un nuevo bloque toda la red tiene que consentir y finalmente ese bloque se almacena en las cadenas de todas las maquinas, sin embargo esta solución abre la posibilidad a nuevos tipos de ataques como por ejemplo el double spend attack, aun así, teóricamente sigue siendo posible “hackear” la BlockChain pero para eso tendrías que modificar los últimos bloques de todas las maquinas de la red lo cual requiere una cantidad inmensa de recursos y por lo tanto no es factible.

Ejemplo de BlockChain para votaciones

Habiendo aprendido los conceptos básicos ahora podemos pensar en como usar BlockChain para almacenar información referente a un sistema de votaciones, vamos a escribir unas cuantas pruebas en Javascript para probar nuestras dos clases, Block y BlockChain.

  it('Generate genesis block', () => {
    voteChain = new BlockChain();
    assert.lengthOf(voteChain.chain, 1);
    assert.equal(voteChain.chain[0].data, 'Genesis block');
  });

Con este test probamos que la cadena se inicializa y el bloque génesis es generado correctamente (la longitud de la cadena es 1 y data del primer bloque contiene el string ‘Genesis block’)

Ahora vamos a agregar unos cuantos bloques a la cadena

  it('Add some blocks', () => {
    voteChain.addBlock(new Block(1, new Date(), { user: 'Manuel', voted: 'PRI' }));
    voteChain.addBlock(new Block(2, new Date(), { user: 'Andres', voted: 'PAN' }));
    voteChain.addBlock(new Block(3, new Date(), { user: 'Julio', voted: 'PRD' }));
    voteChain.addBlock(new Block(4, new Date(), { user: 'Carlos', voted: 'PRI' }));
    voteChain.addBlock(new Block(5, new Date(), { user: 'Ruben', voted: 'PAN' }));
    voteChain.addBlock(new Block(6, new Date(), { user: 'Laura', voted: 'PRD' }));
    assert.lengthOf(voteChain.chain, 7);
  });

Estamos almacenando nombres de personas y el partido político mexicano por el que votaron, un bloque a la vez y al final verificamos que la longitud de la cadena es 7 (incluyendo el bloque génesis). En la vida real esto es mucho mas complicado ya que la gente no podría agregar bloques “solo por que si”, al igual que con Bitcoin se utilizaría una tecnología de PKI (Infraestructura de llave publica) en donde cada transacción de voto deberá ser firmada usando la llave privada (como con la FIEL del SAT) de la persona que emite su voto, de esa manera nadie podría votar a nombre de alguien mas.

Ahora tenemos nuestro test para verificar la integridad de la BlockChain, si la cadena es valida esperaríamos que la función isChainValid nos devolviera true.

  it('Validate chain integrity', () => {
    assert.isOk(voteChain.isChainValid(), 'Block hashes are incorrect'); // this should return true
  });

Observen como en cada uno de los bloques el valor de previousHash es identico al hash del bloque anterior

En la ultima prueba simulamos que alguien modifico el voto de alguien mas, para eso tomamos de forma aleatoria un bloque y cambiamos el valor de su data por el nombre de otro partido político.

  it('Changing random data in the BlockChain', () => {
    const min = 0; // first block id
    const max = 5; // for academic purpose this cannot be 6 (the last block id) due to double spend attack
    const blockId = Math.floor(Math.random() * (max - min + 1) + min); // https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript
    const block = voteChain.chain[blockId];
    block.data = { user: block.data.user, voted: 'MORENA' }; // Changing block value
    block.hash = block.calculateHash(); // Re calculate the current block hash so no one notices the hack
    assert.isNotOk(voteChain.isChainValid(), 'Block hashes are incorrect'); // this should return false
  });

El test, de forma aleatoria, tomo el bloque con index 2 y cambio los valores que tenia en data y eso hizo que el hash resultante de ese bloque cambiara completamente.

hash antes del cambio:
9ecbe54e3e6b3f22a522bbee7f399002f1de2d653c15a74d2d321f27cdfe116b

hash después del cambio:
3e6c8f5c0a734db4bb19483a11022081250171621e5c5c17c21a302d1d9d14d0

Por lo tanto el previousHash del bloque index 3 ya no coincide con el del bloque index 2.

Debido a este cambio la validación de integridad de la cadena fallara (siempre y cuando no modifiquemos los datos del ultimo bloque) y isChainValid() nos devolverá false.

Y eso es todo por ahora, finalmente si quieren descargar este sencillo código para verlo mas a detalle o simplemente para tenerlo lo pueden hacer desde el siguiente repositorio de github alevsk blockchain javascript con los siguientes comandos

$ git clone https://github.com/Alevsk/blockchain-javascript
$ cd blockchain-javascript
$ npm install
$ mocha index.test.js

Resumen

BlockChain nos ofrece ante todo integridad de la información, nos asegura que la información no puede ser cambiada ni eliminada sin que nos demos cuenta, ademas por su naturaleza de ser un sistema distribuido es virtualmente imposible hackear la red, esta tecnología aplicada a un sistema de votaciones nos garantiza que algo como el robo de votos no puede ocurrir y tendríamos total transparencia en las votaciones.

Si quieren aprender mas sobre esta tecnología les recomiendo ver este video en donde se explica con mucho mas detalle como funciona Bitcoin y la BlockChain en general, se abordan muchísimos mas conceptos de los que mencione en este articulo.

Happy hacking 🙂