Passa ai contenuti principali

Blockchain - Introduzione



Blockchain


Cosa è e come funziona ? Cosa significa "minare" ? Come si verificano le transazioni in un sistema anonimo e distribuito ?



Cerco di riportare qui le risposte che ho cercato di darmi su questi argomenti. Provo a suddividere la trattazione in più parti per non risultare eccessivamente lungo.


Il livello di approfondimento è "didattico" cioè cerco di dare dettagli sia architetturali che implementativi ma fermandomi ad un livello adeguato alla comprensione approfondita del meccanismo e non alla implementazione di un sistema reale.

Definizioni

Blockchain è una tecnologia che consente di certificare temporalmente e sequenzialmente una asserzione. In altre parole si ha un registro che certifica il suo contenuto informativo senza un garante e senza fiducia fra le parti. Questa potrebbe essere una definizione quanto più generica possibile della tecnologia, aperta, che sta dietro alle criptovalute ma è utilizzabile anche in altri ambiti.

DLT sta per "Distributed Ledger Tecnology" e sono quelle tecnologie atte a tenere un "Ledger", Libro Mastro in italiano, in maniera distribuita. Il libro mastro tiene la contabilità, cioè i movimenti di denaro, di magazzino, o di scambio di altri beni o servizi. Questa versione "distribuita" fa in modo che i nodi dove è presente una copia di questo libro mastro facciano da garanti del suo contenuto.


SHA256 è un algoritmo di hashing (converte, in maniera non reversibile, qualunque testo in ingresso in una sequenza univoca di caratteri) con l'output caratterizzato dal fatto che, indipendentemente da ciò che si mette dentro, l'hash è sempre di 256 bit, 32 byte che in esadecimale diventano 64 caratteri è (dovrebbe essere) unico in funzione dell'input (dovrebbe perché c'è una seppur remota probabilità di conflitto definita da una dimostrazione teorica).

A parità di input l'output è sempre uguale.
Non reversibile, se non provando tutte le combinazioni possibili
Cambiando minimamente l'ingresso cambia sostanzialmente l'uscita e quindi è impossibile ricondurre due hash di uscita da sha256 a due contenuti simili.


Proof of Work per gestire, mediante una blockchain, una criptovaluta si rende necessario aggiungere complessità computazionale all'operazione di mining. Questo per rendere economicamente (in termini di energia elettrica necessaria) svantaggioso provare a ricalcolare un certo numero di blocchi a forza bruta.

In sostanza si tratta di imporre all'hash ottenuto dall'algoritmo di hashing scelto (nel nostro caso SHA-256) di rispettare alcuni vincoli come ad esempio "iniziale con 00", questa regola di validazione viene detta "Difficulty". Questo implicherà una ricerca a forza bruta per generare una hash così fatto. Cioè si cambierà il contenuto del campo "Nonce" e si riproverà a codificare con SHA-256 fin quando il risultato ottenuto non comincia con "00". Anche nell'uso di blockchain per altri scopi è utile inserire questo meccanismo nella validazione di un blocco per impedire attacchi volti alla ridefinizione di un numero di nodi tali (superiori al 50%) per modificare lo storico.
E' evidente che aumentando la Difficulty si impone una maggiore potenza di calcolo per validare il blocco. In molte criptovalute la Difficulty è dinamica e si adatta alla potenza di calcolo totale stimata messa a disposizione dai miner.
Questo è uno dei metodi usati per imporre un carico computazionale all'operazione di mining.

Nota: nella criptovaluta Bitcoin la "Difficulty" è dinamica e viene adeguata ogni 2016 blocchi minati (al momento in cui scrivo questo avviene circa ogni due settimane).



ICO sta per "Initial Coin Offering", in ambito criptovalute, coincide con il "conio" ed è la creazione del "primo nodo" che contiene la prima transazione.

Cosa è

Blockchain è una tecnologia che consente di avere un "registro" con "scritture" certificate sia a livello di tempo (momento in cui sono state fatte) sia a livello di non modificabilità e quindi di affidabilità. Ogni scrittura che si vuole aggiungere viene inserita in un blocco che viene cifrato ed inserito in un nodo di una catena condivisa in una rete P2P (Pear To Pear). Ogni variazione che si vuole fare al registro può andare solo in coda all'ultima inserita e tutto lo storico viene conservato.
Ogni blocco, ed il suo contenuto, è visibile in chiaro. Ma non è modificabile se non con una scrittura che va aggiunta in coda.


Per definire il contesto si deve fare riferimento alle criptovalute, ma solo perché questa è l'applicazione più pubblicizzata di questa tecnologia la quale è agnostica rispetto al contenuto informativo dei dati che gestisce. Esempi di criptovalute sono i "BitCoin", "Ethereum" e "Dash" solo per citarne qualcuna.



Ogni utente registrato nella rete della criptovaluta ha:



- un Wallet (borsellino letteralmente), che è un software per gestire le sue criptomonete

- una coppia di chiavi pubblica/privata (coppia di chiavi per codifica asimmetriche) dove quella pubblica rappresenta l'indirizzo al quale ricevere moneta virtuale e dal quale inviare moneta virtuale.

Come funziona

I blocchi
Il contenuto informativo sta nei blocchi. Ogni blocco può contenere, nel campo "Dati" una stringa di testo lunga a piacere e che può rappresentare qualunque cosa sia di interesse per chi implementa e mantiene la blockchain:









Ogni blocco è caratterizzato da:

- Nonce : un identificatore univoco del record
- Indice : che lo identifica univocamente in funzione della sua posizione nella catena
- Timestamp : che lo colloca nel tempo
- Data : il vero contenuto informativo costituito da un testo qualsiasi
- Hash : il contenuto del blocco ottenuto dall'algoritmo di hashing usato della parte relativa a Nonce+Indice+Data.
- Precedente : l'hash del blocco che precede il presente

 import java.security.NoSuchAlgorithmException;  
 import utils.Cypher;  
 public class Block {  
  String id = "";  
  String nonce = "";  
  String dati = "";  
  String timestamp = "";  
  String precedente = "";  
  String hash = "";  
  public String getId() {  
  return id;  
  }  
  public void setId(String id) {  
  this.id = id;  
  }  
  public String getNonce() {  
  return nonce;  
  }  
  public void setNonce(String nonce) {  
  this.nonce = nonce;  
  }  
  public String getDati() {  
  return dati;  
  }  
  public void setDati(String dati) {  
  this.dati = dati;  
  }  
  public String getTimestamp() {  
  return timestamp;  
  }  
  public void setTimestamp(String timestamp) {  
  this.timestamp = timestamp;  
  }  
  public String getPrecedente() {  
  return precedente;  
  }  
  public void setPrecedente(String precedente) {  
  this.precedente = precedente;  
  }  
  public String getHash() throws NoSuchAlgorithmException {  
  return Cypher.hash2Base64(this.toString());  
  }  
  public void setHash(String hash) {  
  this.hash = hash;  
  }  
  @Override  
  public String toString(){  
  return this.nonce+this.id+this.dati+this.precedente;  
  }  
 }  

Validazione di un nodo

Una volta che si è generato un blocco nuovo e gli si è inserito il contenuto informativo, cioè il campo "Data", va validato. La validazione di un blocco è ciò che viene definito "mining" cioè "minare" il blocco. Questo processo richiede un certo sforzo computazionale. Tale sforzo è detto "Proof of Work" (vedi definizione nel paragrafo "Definizioni"). Questo sforzo computazionale è demandato ai nodi in cambio di criptovaluta.


Per validare un blocco i vari algoritmi di blockchain prevedono qualcosa di simile a:


0) Genera un codice a caso e lo inserisce in Nonce


1) Generare l'hash mediante SHA256 del blocco. Nello specifico viene sottoposto ad hash la stringa concatenata:

Nonce+Indice+Data+Timestamp+Precedente

Nota che nelle specifiche di Bitcoin è previsto il "doppio SHA-256" (vedi paragrafo "SHA-256 Doppio").

2) Verificare se l'hash così ottenuto rispetta la "Difficulty" impostata (inizia per "00" ad esempio).

3) Se non rispetta la difficulty ripeti dal punto 0)

4) Se la rispetta valida il nodo inserendo nel campo "hash" di questo l'hash ottenuto con SHA-256 che rispetta la difficulty.

Il blocco è validato, è inserito nella copia della catena che ha il mio nodo ed è ora da propagare sugli altri nodi.

Qui vediamo la classe che si occupa del crypting:


package utils;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class Cypher {

    public static byte[] hash256(String pas) throws NoSuchAlgorithmException {
        java.security.MessageDigest d = null;
        d = java.security.MessageDigest.getInstance("SHA-256");
        d.reset();
        d.update(pas.getBytes());
        return d.digest();
    }

    public static String hash2Base64(String pas) throws NoSuchAlgorithmException {
        return Base64.getEncoder().encodeToString(hash256(pas));
    }
    public static byte[] hash2Base64Byte(String pas) throws NoSuchAlgorithmException {
        return Base64.getEncoder().encode(hash256(pas));
    }
   
    public static void main(String[] args) throws NoSuchAlgorithmException {
        System.out.println(hash2Base64("CiaoATutti28"));
    }

}



Transazione

Una "transazione" è il passaggio di criptovaluta, o parte di essa, da un detentore ad un altro detentore. Questo, in un contesto di blockchain per criptovalute, costituisce il "contenuto informativo" (citato prima). In una blockchain non rivolta a criptovalute può essere una "registrazione" di uno scambio fra utenti o una registrazione di un fatto assoluto.

package mine;

import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.Random;
import model.Block;
import utils.Cypher;
public class ValidateBlock {

  public static String seal = "00";
  public static String givenRandomString() {

   int leftLimit = 97; // letter 'a'
  int rightLimit = 122; // letter 'z'
  int targetStringLength = 5;
  Random random = new Random();
  StringBuilder buffer = new StringBuilder(targetStringLength);

  for (int i = 0; i < targetStringLength; i++) {

   int randomLimitedInt = leftLimit + (int) (random.nextFloat() * (rightLimit - leftLimit + 1));

   buffer.append((char) randomLimitedInt);

  }
  String generatedString = buffer.toString();
  return generatedString;
 }


  public static String getSeal() {
  return seal;
 }


  public void setSeal(String seal) {
  this.seal = seal;
 }


  /**

  * Dato un blocco cerca una codifica SHA256 in BASE64 che cominci con il numero

  * di "Difficulty" pari alla lunghezza dei caratteri definiti in "Seal". Appena

  * la trova valorizza il timestamp del nodo

  * 

  * @param b

  * @return

  * @throws NoSuchAlgorithmException

  */

 public static boolean validateBlock(Block b) throws NoSuchAlgorithmException {

  boolean ret = false;
  String validHash = "11";
  System.out.println("Inizio mining"+ new Timestamp(System.currentTimeMillis()));
  String tempNonce = null;
  while (!validHash.substring(0, getSeal().length()).equals(getSeal())) {
   tempNonce = givenRandomString();
   b.setNonce(tempNonce);
   validHash = Cypher.hash2Base64(b.toString());
   System.out.println(validHash);

  }

  Timestamp timestamp = new Timestamp(System.currentTimeMillis());
  b.setTimestamp(String.valueOf(timestamp.getTime()));
  ret = true;
  System.out.println("Fine mining"+ new Timestamp(System.currentTimeMillis()));
  b.setHash(validHash);
  b.setNonce(tempNonce);

  return ret;


  }


  public static void main(String[] args) throws NoSuchAlgorithmException {

   Block b = new Block();
  b.setDati("Ciao a tutti quanti");
  b.setId("1");
  b.setNonce("0000");
  if (validateBlock(b)) {
   System.out.println("Id = " + b.getId());
   System.out.println("Nonce = " + b.getNonce());
   System.out.println("Dati = " + b.getDati());
   System.out.println("Timestamp = " + b.getTimestamp());
   System.out.println("Blocco precedente = " + b.getPrecedente());
   System.out.println("Hash = " + b.getHash());

  }
 }

}

Validazione della transazione

La validazione di un transazione consiste nel recuperare i dati delle parti coinvolte nella transazione (o registrazione, se ce ne sono). Quindi se un utente A deve trasferire qualcosa all'utente B deve, semplicemente (usando il suo wallet) dichiarare che A cede a B il valore X. Dopo firma la transazione con la sua chiave privata. Prende il tutto e lo invia alla rete P2P per la validazione.
Uno o N nodo/i "miner" prenderà in carico la richiesta di transazione. Recupererà dai nodi della catena il "credito" dell'utente A, per verificare se ha credito sufficiente a compiere la transazione richiesta. Se sì raccoglierà questa richiesta in un nuovo nodo nel quale inserirà altre richieste di validazione di transazioni che è riuscito a validare e proverà a validare il nodo (vedi paragrafo "Validazione di un nodo"). Il primo miner che riesce a compiere la validazione illustrata risulta il vincente su gli altri che può quindi proporre il nodo all'inserimento nella blockchain e riceverà un premio in bitcoin per il lavoro svolto.
Il nodo verrà inserito alla fine della catena come nodo nuovo e verrà distribuito nelle varie copie, in giro per la rete, del database delle transazioni (cioè la catena dei nodi).

SHA-256 Doppio

Facciamo un esempio di SHA-256 singolo del contenuto "ciao" con il comando:

echo -n ciao |openssl dgst -sha256


b133a0c0e9bee3be20163d2ad31d6248db292aa6dcb1ee087a2aa50e0fc75ae2

Sha256 "doppio maccheronico" del contenuto "ciao" ottenuto facendo ripassare in Sha256 il risultato del primo passaggio:


echo -n b133a0c0e9bee3be20163d2ad31d6248db292aa6dcb1ee087a2aa50e0fc75ae2 |openssl dgst -sha256



Risultato:


c98b1c10cf6d3fd3a32ee8a92e9a17e80a1172a363d479982aa3877503d6c8b2




Sha256 doppio del contenuto "ciao":

echo -n ciao |openssl dgst -sha256 |openssl dgst -sha256

5eb8d9727ec6fa7144d55e03a8271df991f31f01a6330ce994a05bd2441db49f

Differiscono perché ogni rappresentazione su schermo della sequenza di byte generata dallo sha256 viene codificata in esadecimale per renderla come "caratteri stampabili" e quindi si ottiene una stringa di 64 byte e quindi 64 caratteri

To be continued...

Abbiamo il nostro blocco con il nostro SHA-256 doppio che inizia con 00. Nei prossimi post della serie passeremo alla rete pear to pear dei nodi.

Riferimenti






Licenza Creative Commons
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale

Commenti

Post popolari in questo blog

Telecamere Ip con accesso "nascosto"

Telecamere Ip con accesso "nascosto" Storia triste di un auto-hacking obbligato che mi ha fatto scoprire come la nostra privacy è realmente messa a rischi. Storia Ho acquistato dal mercatino/fiera del Radioamatore di Fasano quattro telecamere IP. La scatola riporta "Smart Camera" LF4810. Ne ho montata una e testata in tutte le sue funzionalità per oltre un mese. Chiaramente la manualistica scarsissima, come da tradizione in questi prodotti cinesi di costo molto concorrenziale, consiste in un "pieghevole" di 4 facciate. Chiaramente non erano documentate le impostazioni necessarie per attivare i protocolli ONVIF e RTSP che mi sono indispensabili per l'uso che ne devo fare. Nonostante questa scarsa documentazione dopo l'installazione base fatta con l'apposita app: tutto sembrava corretto. Chiaramente la prima azione che ho compiuto è stata quella di cambiare la password che di default è "123". Subito dopo h

Dynamic DNS con Duckdns.org in HTTPS

Obiettivo Avere un dominio https con certificato valido da usare come endpoint pubblico per Homeassistant e per un WebHook per i bot telegram. Fase 1 Registrazione del dominio in un servizio di dynamic DNS come https://www.duckdns.org/   : Scegliere per quale sistema operativo installare il client che si occuperà dell'aggiornamento dell'ip: Seguire la semplice guida per la configurazione del processo cron: Fase 2 Creazione del certificato e installazione sul server. Di tutto questo si occuperà una applicazione che si chiama certbot. $ sudo add-apt-repository ppa:certbot/certbot $ sudo apt install python-certbot-apache $ sudo certbot --apache -d ol3.duckdns.org -d www.ol3.duckdns.org Fase 3 Esporre il servizio https sulla rete pubblica. Aprire o reindirizzare la porta 443 verso l'host sul quale si è fatta la configurazione di certbot dal proprio router. Il certificato di certbot è valido per novanta giorn

JHipster - Uso base

Cosa è JHipster è un "generatore di applicazioni" che fornisce tutto lo stack necessario ad implementare una applicazione web e/o a microservizi basata su Spring Boot e AngularJs. E' dotato di un marketplace di componenti già pronte: https://www.jhipster.tech/#modules E' dotato di uno strumento web per la modellazione dello schema E-R: https://start.jhipster.tech/jdl-studio/ Prerequisiti - Java 8  - Node.js (usare la versione LTS 64-bit) - NPM viene installato con Node.js ma va aggiornato      $ npm install -g npm - Per usare il JHipster Marketplace, installare Yeoman:       $ npm install -g yo Uso base Gli step, presi dal sito ufficiale sono questi: 1. Installare JHipster:       $ npm install -g generator-jhipster Nota: per installare una versione specifica del generator:   $ npm install -g generator-jhipster@6.0.5 2. Crea una nuova directory ed entra dentro questa:   $ mkdir myApp   $ cd M yApp 3. Eseguire JHipster e