3. Certificar información

En esta sección, te explicaremos cómo empezar a certificar archivos con Smartcheck.

3.1. Envío de datos a certificar

3.1.1. ¿Qué se puede certificar?

Los elementos a certificar son las huellas hash de los archivos a registrar y los metadatos asociados.

Las huellas hash son códigos únicos que se generan a partir de los archivos mediante un algoritmo criptográfico. Los metadatos son datos adicionales que describen o complementan los archivos, como el nombre, el tamaño, el tipo, la fecha, etc. Para enviar los datos a certificar, debes enviar una petición POST al endpoint /create-tree-and-register-merkle-root con el token de tu sesión, el identificador del proyecto y los datos a certificar. Si la petición se realiza con éxito, recibirás una respuesta con el código del contrato donde se registraron los datos.

3.1.1.1. ¿Qué es un Hash?

Un código hash es una sucesión alfanumérica de longitud fija que identifica o representa a un conjunto de datos determinados. Es una función matemática que convierte cualquier entrada de datos en una cadena de caracteres alfanuméricos de longitud fija. Esta cadena de caracteres es única para cada archivo y se utiliza para verificar la integridad de los datos. Es decir, el código hash es una huella digital única que se genera a partir del archivo original y se utiliza para verificar que el archivo no ha sido modificado.

Nota: Code Contract utiliza por defecto códigos hash de tipo SHA-256

3.1.2. Envío de solicitud de certificación

  • Petición por POST:
    curl -X POST\
    -H "Accept: application/json"\
    -H "Content-Type: application/json"\
    "/api/smart-check/create-tree-and-register-merkle-root"
  • Cuerpo de la petición:
    {
        item_hashes_and_metadata:[
            {
                item_hash:  string
                metadata:[
                    {
                        key: string
                        value: string
                    }
                ]
            }
        ]
        smart_check_merkle_id: string
    }
  • Ejemplo:
    {
        "item_hashes_and_metadata":[
            {
                "item_hash": "d0ada7e1d0fb7d08cde6e34fd4fadd14373ccae11306a444dbff1204d7a247f7",
                "metadata":[
                    {
                        "key": "Archivo",
                        "value": "instrucciones.txt"
                    }
                ]
            }
        ],
        "smart_check_merkle_id": "63c0004fb48e545d74c2851d"
    }

3.1.3. ¿Cómo se obtiene el código Hash de un archivo?

A continuación te mostramos algunos ejemplos en los lenguajes de programación más populares

3.1.3.1. Python

    import hashlib

    def hash_file(filename):
        """Esta función devuelve el hash SHA-256 del archivo pasado como argumento"""
        # crea un objeto hash con sha256
        h = hashlib.sha256()

        # abre el archivo en modo lectura binaria
        with open(filename,'rb') as file:
            # bucle hasta el final del archivo
            chunk = 0
            while chunk != b'':
                # lee solo 1024 bytes a la vez
                chunk = file.read(1024)
                h.update(chunk)

        # devuelve la representación hexadecimal del hash
        return h.hexdigest()

3.1.3.2. Java

    import java.io.FileInputStream;
    import java.security.MessageDigest;

    public class FileHashExample {
        public static void main(String[] args) throws Exception {
            String filePath = "path/to/your/file.txt";

            // Create a SHA-256 message digest
            MessageDigest digest = MessageDigest.getInstance("SHA-256");

            // Read the file and update the digest
            try (FileInputStream fis = new FileInputStream(filePath)) {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    digest.update(buffer, 0, bytesRead);
                }
            }

            // Get the hash value
            byte[] hashBytes = digest.digest();

            // Convert the hash bytes to a hexadecimal string
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                hexString.append(String.format("%02x", b));
            }

            String hash = hexString.toString();
            System.out.println("SHA-256 hash: " + hash);
        }
    }

3.1.3.3. PHP

    $file = 'path/to/your/file.txt';

    // Calculate the SHA-256 hash of the file
    $hash = hash_file('sha256', $file);

    echo "SHA-256 hash: " . $hash;

3.1.3.4. 'C#'

    using System;
    using System.IO;
    using System.Security.Cryptography;

    class Program
    {
        static void Main(string[] args)
        {
            string filePath = "path/to/your/file.txt";

            // Create a SHA-256 hash object
            using (SHA256 sha256 = SHA256.Create())
            {
                // Read the file and compute the hash
                using (FileStream stream = File.OpenRead(filePath))
                {
                    byte[] hash = sha256.ComputeHash(stream);
                    string hashString = BitConverter.ToString(hash).Replace("-", String.Empty);

                    Console.WriteLine("SHA-256 hash: " + hashString);
                }
            }
        }
    }

3.1.3.5. Javascript

El siguiente ejemplo requiere el módulo crypto de Node.js

    const crypto = require('crypto');
    const fs = require('fs');

    const filePath = 'path/to/your/file.txt';

    // Read the file and compute the hash
    fs.readFile(filePath, (err, data) => {
    if (err) throw err;

    const hash = crypto.createHash('sha256').update(data).digest('hex');

    console.log('SHA-256 hash:', hash);
    });

3.1.4. ¿Cómo funciona?

El proceso de registro en la cadena de bloques se ejecuta utilizando un árbol Merkle siguiendo los siguientes pasos:

  1. Generación del árbol Merkle Los hashes de los archivos y sus metadatos asociados son organizados en un árbol Merkle. Este árbol se construye dividiendo repetidamente los hashes en pares y calculando el hash del par combinado hasta que se llega a un único hash en la cima, conocido como la "raíz Merkle" o "Merkle root".

  2. Cálculo del Merkle Root Una vez que se ha construido el árbol, se obtiene la raíz Merkle, también conocida como "Merkle Root". Este valor único y final se utiliza para representar todo el conjunto de datos en el árbol.

  3. Registro en Blockchain El Merkle Root se registra en la cadena de bloques. Dado que la raíz Merkle se deriva criptográficamente de todos los hashes en el árbol, cualquier cambio en un hash individual se reflejará en la raíz, lo que permite detectar cualquier alteración en los datos originales.

3.1.4.1. ¿Qué es un arbol Merkle?

Un árbol Merkle, nombrado en honor al científico Ralph Merkle, es una estructura de datos jerárquica utilizada para verificar y validar la integridad de información, como archivos o datos, comunmente utilizado en sistemas descentralizados como la tecnología blockchain. Esta estructura se basa en la propiedad criptográfica de resumen o "hash", donde se procesa un conjunto de datos y se genera una huella digital única llamada Merkle Root que representa esos datos.

Alt text

En este ejemplo podemos ver cómo las pruebas Tx1 hasta Tx8 se convierten en arbol Merkle dando lugar a un Merkle Root Hash 12345678.

Hay que tener en cuenta que para que el árbol Merkle funcione, el conjunto de datos debe ser procesado en orden y que, para cada elemento (Tx1, Tx2 etc..) el sistema creará automáticamente un código de verificación intermedio también llamado Checksum, cada Checksum dará lugar a la huella Hash correspondiente (Hash 1, Hash 2 etc..) que será la base de nuestro árbol.