El registre descentralitzat de certificats digitals revocats

Recursos pràctics

Una introducción práctica a la infraestructura web de clave pública y los contratos inteligentes con la excusa de mejorar la consulta del estado de revocación de un certificado digital.

Contingut:

Parte I

La introducció

Quan accedim a un lloc web a través del nostre navegador, esperem que la informació que intercanviem amb aquest lloc sigui confidencial i integra. No volem que tercers vegin les nostres credencials d’accés al banc o que algú sàpiga quantes criptomonedes estem comprant en el nostre exchange favorit. Per això afegim la “s” de segur al “http” cada vegada que introduïm una adreça web en la barra d’adreces del nostre navegador. De hecho, hoy en día se suele añadir de forma automática, gairebé sempre.

https

 

El xifratge de la informació

Per aconseguir aquesta comunicació segura la informació intercanviada es fa inintel·ligible per a tot aquell que no tingui la clau. A això se li diu xifrar lla informació. Tant les peticions d’informació que fa el navegador al lloc web com la informació de resposta que el lloc web envia al navegador de tornada estan xifrades. 

 

La clau de sessió

La clau secreta és acordada entre les dues parts, navegador i lloc web. Aquesta clau s’anomena clau de sessió, perquè es renegociarà entre les parts cada poc temps. Si imaginem que les claus són colors, la informació xifrada pel servidor amb un color només pot ser desxifrada pel navegador utilitzant aquest mateix color i cap altre. Un adversari, algú escoltant, només pot veure la informació intercanviada si coneix el color utilitzat o és capaç de deduir-lo. Aquest tipus de xifratge que utilitza una sola clau es diu simètric. És molt adequat perquè el xifratge simètric és molt ràpid i segur. A més ens permet, amb certes cauteles, xifrar grans quantitats d’informació.

Infografía clave de sesion

Per aconseguir establir una clau secreta compartida en presència de tercers, les dues parts implicades utilitzen un protocol, unes regles d’intercanvi de clau. Continuant amb l’analogia dels colors, aquest protocol es basa en la idea que és fàcil barrejar dos colors però molt difícil separar-los després. Les dues parts es posen d’acord públicament en un color comú inicial. Cadascú barreja aquest color comú amb el seu propi color secret per obtenir un color barrejat que enviarà a l’altra part. Finalment, cada part barrejarà el color rebut amb el seu color secret i així obté un color compartit igual que el de l’altra part. La figura següent ho explica molt bé:

 

Infografía clave secreta

En resum, ambdues parts barregen el color comú amb els dos colors secrets, un de cada part.

Aquest protocol permet acordar l’ús d’una clau compartida de manera segura. Però en la seva versió bàsica o anònima, no garanteix amb qui estic intercanviant informació. És a dir, no és autenticat. No es comprova que les parts implicades siguin qui diuen ser. Això permetria a un atacant col·locar-se entre les dues parts sense que cap d’elles se n’adoni, creient ambdues que només estan elles dues en la comunicació. Això es diu atac d’intermediar

 o d’home al mig.

 

La signatura digital

Una solució per saber amb qui estem parlant és que els missatges enviats estiguin signats digitalment.

La signatura digital és una de les aplicacions de la criptografia asimètrica.

En lloc d’utilitzar la mateixa clau per xifrar i desxifrar una informació, la criptografia asimètrica n’utilitza dues. És a dir, tenim una parella de claus vinculades de tal manera que el que xifra una de les claus només pot ser desxifrat per l’altra i cap altra. La clau que s’utilitza per xifrar informació és una clau secreta, privada. L’altra és la clau pública, la podem lliurar a tothom. Amb la clau pública que pot desxifrar la informació que he xifrat amb la clau privada.

Cal recalcar que en realitat estem enviant dos objectes. D’una banda, el missatge públic i, per una altra, una signatura d’aquest missatge. Si canvio el missatge, la signatura no serà vàlida. La signatura és el missatge xifrat amb la clau privada. Però, la criptografia de clau asimètrica és lenta, molt lenta, i no pot xifrar missatges gaire llargs. Per això el que es xifra, el que se signa, és una representació del missatge, anomenada empremta digital.  Aquesta representació és un altre missatge d’una mida fixa més petita, però prou gran per evitar col·lisions. D’aquesta manera, tot missatge, de qualsevol mida, pot representar-se per aquesta empremta digital. El canvi d’una sola lletra en el missatge canviarà completament la seva empremta.

Això vol dir que aquí no hi ha confidencialitat de cap tipus. Tothom pot desxifrar els meus missatges xifrats. Només han d’utilitzar la clau pública, que és pública. Té sentit, ja que es tracta d’una signatura. El que sí que garanteix

és que només jo he pogut xifrar aquest missatge, com a controlador exclusiu d’aquesta clau secreta. I és el que equival a una signatura.

En resum, per signar un missatge calculem la seva empremta digital i la xifrem, i obtenim un missatge que anomenarem signatura. Per verificar una signatura la desxifrem i verifiquem que el valor obtingut és l’empremta digital del missatge.

 

Els certificats digitals

Els navegadors han d’obtenir les claus públiques de les web a les quals accedim i estar segurs que són autèntiques per aconseguir establir una comunicació segura. Quan no podem verificar si les claus públiques corresponen al web a què estem intentant accedir el nostre trànsit podria ser interceptat i manipulat per un tercer sense adonar-nos-en.

Un certificat digital vincula una clau pública amb una identitat i altres dades. En el cas d’un certificat d’autenticació web, la identitat es refereix al nom de domini. A més els certificats digitals inclouen la data des de la qual és vàlid, que sol ser la data d’emissió, i la data fins que serà vàlid.

 

Les autoritats de certificació

Totes les dades que surten juntes en un certificat són signades digitalment per una autoritat de certificació (AC), també anomenada entitat emissora. L’AC s’encarrega de verificar la validesa de totes aquestes dades incloses al certificat abans d’emetre’l, abans de signar-lo.

L’AC signa digitalment el certificat utilitzant el seu propi certificat. Com que tot certificat és emès per una AC es crea una cadena de confiança d’autoritats de certificació. Aquesta cadena acaba quan una AC emet un certificat que es verifica a si mateix i que es diu certificat arrel.

Establir la identitat d’un certificat sense una autoritat de certificació es un viejo anhelo. Hasta hoy no lo hemos logrado, pero estamos cerca.

 

El poder dels navegadors

Tots els navegadors venen preconfigurats amb una sèrie d’AC que permeten verificar i acceptar certificats d’autenticació de llocs web emesos per aquestes AC. Cada navegador té el seu propi procediment per afegir o eliminar les AC que venen preconfigurades. Un certificat emès per una AC pot ser acceptat en un navegador i no en un altre, i això sol crear problemes estranys. Al final, un grapat de persones responsables de cada navegador decideixen quines AC són incloses en aquest “petit” llistat d’AC confiables que garanteixen la nostra seguretat en les comunicacions. Sempre ha estat així al món humà.

 

 

El poder de les autoritats de certificació

Les AC poden emetre certificats per a qualsevol domini a la seva discreció, com va fer Symantec emetent certificat “de prova” amb el domini de google. Aquests certificats podrien haver estat utilitzats per llançar atacs de phising molt efectius.

Amb el poder que tenen les AC, les fa objectius molt desitjables per als furons, com ho va ser DigiNotar. También los gobiernos pueden abusar de su poder como hizo Siria intentando un ataque de intermediario con FaceBook.

Una AC pot ser deshonesta, o pot estar compromesa d’alguna manera. Sigui volent o sense voler, una AC compromesa pot emetre certificats amb claus públiques falses, per a qualsevol domini. Tot navegador que confiï en aquesta AC maliciosa acceptarà sense parpellejar els certificats per ella emesos. Un atacant pot falsificar certificats per a qualsevol web que desitgi i no hi haurà manera de diferenciar-los de certificats autèntics.

 

La infraestructura de clau pública

La infraestructura de clau pública

són les polítiques i procediments, el programari, el maquinari, que es necessiten per gestionar certificats digitals. Gestionar vol dir com emetre’ls, utilitzar-los, emmagatzemar-los, revocar-los, eliminar-los…

Algunes de les funcions d’una AC poden ser delegades. Per exemple, l’AC delega en l’autoritat de registre (AR) la verificació de les dades d’identitat que hi ha en un certificat.

Les entitats de validació (AV) proporcionen els serveis necessaris per comprovar que un certificat continua sent vàlid en un moment determinat. El certificat té entre les seves dades un període de validesa. No cal una AV per verificar si el certificat és dins d’aquell període, més enllà de tenir un rellotge correctament sincronitzat. Però sí en els casos en els quals el certificat o alguna de les seves dades deixen de ser vàlids per alguna altra raó.

 

 

El problema de la infraestructura de clau pública

El model d’infraestructura pública és fràgil. Por una parte cualquier AC puede emitir un certificado para cualquier dominio. Por otra parte, no hay forma de saber qué certificados ha emitido una AC. Para reducir el problema se han propuesto muchas soluciones, que no han funcionado. Actualmente se usa un registro público transparente y verificable de la emisión de certificados de cada AC per reduir els certificats emesos per error o malintencionadament.

 

L’estat de revocació d’un certificat

El temps de vida d’un certificat és relativament llarg, en l’ordre de mesos. Alguna dada del certificat pot deixar de ser correcta, es pot perdre el control de la clau privada associada al certificat, l’entitat emissora pot haver estat compromesa, s’ha perdut… Però el certificat és un objecte immutable. Per això s’estableixen diferents mecanismes que permeten consultar l’estat del certificat. Almenys l’estat que tenia fa poc temps, en l’ordre d’hores.

Un certificat està “revocat” quan un perd la seva validesa per altres causes que no siguin l’expiració.

Els serveis per verificar l’estat de revocació d’un certificat els proporciona l’AV i els mitjans per accedir-hi solen anar al mateix certificat. Aquests serveis són un altre taló d’Aquil·les de la infraestructura de clau pública.

Un navegador no pot estar segur que els servidors de l’AV seran accessibles per verificar l’estat d’un certificat. Per exemple, un portal captiu només permet autenticar-se en una adreça HTTPS però bloqueja el trànsit a qualsevol altra adreça, incloent els serveis de consulta de revocació del certificat. Si el navegador no accepta el certificat, quan no pugui verificar el seu estat no es podrà accedir al lloc web, i deixarà de funcionar. D’altra banda, un tall, per petit que sigui, dels serveis de consulta d’estat implica un punt únic de fallada.

Per això, molts navegadors consideren els errors de xarxa a l’hora de consultar l’estat de revocació d’un certificat com a fallades que simplement són ignorades. A més, els costos de la verificació són més temps de connexió, pàgines més lentes i possibles problemes de privacitat perquè les AV poden registrar els dominis consultats i des de quina ip… Per això, alguns navegadors utilitzen un mecanisme que envia les llistes de certificats revocats de totes l’AC a cada navegador, que complica lleugerament les coses a un atacant.

 

Les llistes de revocació de certificats

Un dels primers serveis per a la consulta de l’estat de revocació d’un certificat va ser utilitzar una llista (CRL). En aquesta llista hi ha l’identificador del certificat amb un estat de revocació. Si el certificat no surt a la llista, serà vàlid. Els certificats solen incloure un o diversos serveis des dels quals descarregar aquestes llistes.

Les llistes s’actualitzen cada cert temps per reflectir els canvis. Un dels problemes amb aquestes llistes és que creixen de manera desmesurada amb el temps, poden ser problemàtiques respecte de la privacitat de dades, o simplement no estan prou actualitzades…

 

La consulta de revocació d’un certificat en línia

Aquest petit caos amb les llistes de revocació va desembocar en la creació d’un nou servei que permetés comprovar l’estat d’un certificat en concret directament (OCSP).E

En lloc de descarregar una llista cada cert temps, els navegadors poden fer les consultes cada vegada i només per al certificat que estan utilitzant. Però això va crear una dependència molt més gran entre l’AV i el navegador. Els atacs de denegació de servei són més fàcils. La disponibilitat del servei es torna més crítica. La privacitat empitjora…

Per alleujar algun d’aquests problemes s’estableixen protocols per enviar l’estat de revocació juntament amb el certificat del lloc web però creen els seus propis problemes.

Cada dia surten noves propostes per a la consulta de l’estat de revocació d’un certificat, com a solució específica o englobada en una solució més general.

 

La cadena de blocs i els contractes intel·ligents

La cadena de blocs (blockchain) és un registre públic i descentralitzat de dades que s’actualitza, només afegint entrades en forma de transaccions, mitjançant el consens de tots els participants. Les dades s’emmagatzemen de manera redundant en molts llocs. Bitcoin, el precursor de la blockchain, permet mantenir un registre públic dels intercanvis de valor entre els participants. És molt difícil de censurar, ja que no té una entitat central que el controli. Serà molt difícil prohibir-lo sense que es consideri un atac a la mateixa llibertat d’expressió i el dret a comunicar-nos. Ethereum, per la seva banda, fa ús d’una blockchain per mantenir un consens no només sobre la informació, sinó sobre petites aplicacions que manipulen aquesta informació, i es converteix en una espècie d’ordinador global públic compartit. Ethereum anomena aquestes petites aplicacions contractes intel·ligents.

 

LLa blockchain proporciona nous casos d’ús que prèviament no es podien resoldre de manera satisfactòria Proporciona immutabilitat, una vegada escrit un registre en un bloc no es pot alterar perquè requeriria alterar tots els blocs anteriors que requereixen el consens de tots els participants. És un sistema descentralitzat que evita molts atacs com la denegació de servei. És transparent, la blockchain és visible públicament. És ràpida i més barata, en relació amb sistemes equivalents amb les mateixes garanties.

 

La llista de certificats revocats descentralitzada

Explorarem les possibilitats d’utilitzar blockchain com a registre de l’estat de revocació dels certificats emesos per una AC. L’anomenarem Decentralized Certificate Revocation List (DCRL). 

Definirem i desplegarem un contracte intel·ligent d’Ethereum per gestionar la llista. Definirem una nova extensió del certificat que inclogui l’adreça del contracte intel·ligent. Crearem uns certificats d’exemple i implementarem les eines per revocar un certificat i per consultar-ne l’estat.

Parte II

Els nodes i els clients d’Ethereum

Un nodo de ethereum es una aplicación que permite interactuar con Ethereum. Una vez instalada permite verificar las transacciones de cada bloque y enviar a la red nuevas transacciones. Hay distintas implementaciones de clientes de Ethereum. Aquí vamos a usar el cliente geth.

Un node pot llançar-se amb diferents maneres. El mode complet (full) emmagatzema totes les dades de la blockchain, participa en la validació de blocs, verifica blocs i estats… El mode lleuger només valida les dades de les capçaleres dels blocs i s’utilitza en dispositius embeguts o de pocs recursos.

Nosaltres utilitzarem el mode “fast”, que només utilitza l’estat més recent de la blockchain.

Descarreguem el client del web d’Ethereum. Deixem per a la reflexió com estarem segurs que hem accedit al web autèntic i que hem descarregat un paquet legítim.

https://geth.ethereum.org/downloads/

Per exemple, utilitzant wget per a una distribució linux 64bits

wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.25-e7872729.tar.gz

Descomprimim el paquet i accedim al directori

tar xvf geth-linux-amd64-1.9.25-e7872729.tar.gz
cd geth-linux-amd64-1.9.25-e7872729

i llancem el node utilitzant aquesta línia d’ordres

$ geth  --goerli --syncmode "light"  --http --
http.corsdomain="https://remix.ethereum.org"  --allow-insecure-unlock

 

Alguns dels paràmetres importants de geth

 

–http Activa el servei JSON-RPC, que permet a altres aplicacions utilitzar el node via API
 –http.corsdomain Només es permetrà l’accés a l’API des de “https://remix.ethereum.org” que serà l’entorn amb què despleguem el contracte intel·ligent 
–goerli Utilitzarem la xarxa de proves Görli. Ethereum disposa de diverses xarxes de proves i una de producció. Görli és una xarxa proof-of-authority que funciona amb clients Parity, Geth i d’altres
 –syncmode Utilitzarem el mode de sincronització “light”, per defecte és “fast”
–datadir El directori on s’emmagatzemaran les dades de la blockchain. Ocuparà uns 12GB si utilitzem un node “fast” i 500MB si utilitzem un node “light”. Si no ho especifiquem, utilitzarà el directori per defecte que és ~/.ethereum/goerli
 –cache Augmentar a 2048 la memòria millora el rendiment en cas de sincronització “fast”
–allow-insecure-unlock Permet desbloquejar un moneder alhora que s’utilitza l’API, la qual cosa no és recomanable fora de desenvolupament.
console Llança una consola JavaScript per interactuar amb el node

 

El mode “light” és experimental, però prou estable com per a la nostra comesa.

INFO [02-12|09:27:12.511] Starting Geth on Görli testnet... 
[...]
WARN [02-12|09:27:12.689] Light client mode is an experimental feature 

 

En llançar el node començarà a sincronitzar-se amb la xarxa automàticament. Recorda que  aquesta sincronització trigarà diverses hores en el cas que el mode sigui “fast”.

Per interactuar amb el node des d’una altra terminal utilitzem l’ordre attach:

$ geth  --goerli attach

Welcome to the Geth JavaScript console!
[..]
To exit, press ctrl-d

 

En introduir a la consola l’ordre eth.syncing obtindrem l’estat de sincronització del node o false si està completament sincronitzat. eth és un objecte que permet interactuar amb els contractes intel·ligents i la mateixa blockchain.

> eth.syncing
{
  currentBlock: 213539,
  highestBlock: 4264547,
  knownStates: 511823,
  pulledStates: 502449,
  startingBlock: 0
}

mb l’ordre eth.blockNumber obtindrem l’últim bloc processat pel nostre node.

> eth.blockNumber
4269342

 

La cartera

Per enviar transaccions a la blockchain necessitem unes credencials a més del node. Les credencials són una clau pública i una altra de privada. A partir de la clau pública obtindrem un número de compte o adreça (address). Utilitzant missatges signats digitalment amb la nostra clau privada enviem operacions en forma de transaccions a la blockchain.

El lloc on desem aquestes claus es diu cartera o moneder (wallet) i té associat un balanç, uns ether, que ens permetran enviar les transaccions a la xarxa. Crear un nou compte no requereix cap tipus d’autorització. Ethereum és una xarxa no permissionada.

No tenim cap compte en el nostre node local. Per afegir-ne un utilitzem l’objecte personal que s’encarrega d’interactuar amb els comptes del node:

> personal.newAccount()

 

Establim una contrasenya, que podem deixar en blanc per a les proves. Per obtenir els comptes que tenim escrivim:

> personal.listAccounts
["0x673ce1bda1ca6a7d969b8f44e44d78ce9ef11691"]

 

encara que també podem utilitzar eth.accounts, més habitual. El balanç del compte resideix en la blockchain, no en el compte i, per tant, per obtenir-lo utilitzem mètode getBalance de l’objecte eth, que ens donarà els Wei en el compte.

> eth.getBalance(eth.accounts[0])
0

 

Per afegir fons accedim a algun dels serveis gratuïts de subministrament per a la xarxa Görli. Introduirem la nostra adreça i amablement ens transferiran una petita quantitat d’ethers. En producció utilitzarem algun exchange per adquirir ethers a canvi d’euros o dòlars.

Per exemple, podem accedir a https://goerli-faucet.slock.it/

En uns instants tindrem els fons disponibles en el nostre compte.

 

El contracte intel·ligent

Ethereum executar petites aplicacions mitjançant una màquina virtual EVM). Las aplicaciones pueden entenderse como una máquina de estados distribuida. La EVM permite modificar esa máquina de estados global mediante instrucciones de bajo nivel u opcodes. Existen varios lenguajes de programación que compilan a instrucciones de EVM. El más usado es Solidity. És un llenguatge orientat a objectes amb tipus específics, modificadors de funcions per crear precondicions, gestió d’esdeveniments…

El nostre contracte intel·ligent és molt senzill. Conté la llista de certificats que hagin estat revocats. Si surten a la llista, han estat revocats, sense més informació inicial. Cada AC gestionarà el contracte intel·ligent que gestiona la llista

Els certificats es localitzen mitjançant el seu identificador de subjecte (Subject Key Identifier, SKID). L’SKID és una extensió dels certificats que es calcula a partir de la seva clau pública.

Extensions: 
    2.5.29.14 (Subject key identifier)
        Identifier: ee:09:e5:4e:30:60:2b:fa:c7:52:78:86:b9:b9:9e:fb:a6:7f:20:0b

 

El codi del contracte intel·ligent té un mapa que associa un enter de 256bits amb un valor booleà. Té dues funcions, una per a la consulta de l’estat d’un certificat i una altra per revocar un certificat, ambdós identificats mitjançant el SKID. El mètode revoke només pot ser cridat pel propietari del contracte.

pragma solidity >=0.7.0 <0.8.0;

contract DCRL {

    address owner;

    constructor()  {
        owner = msg.sender;
    }

    mapping(uint256 => bool) revoked;

    function revoke(uint256 id) public {
        require(owner == msg.sender);
        revoked[id]=true;
    }

    function has(uint256 id) public view returns (bool){
        return revoked[id];
    }

}

 

L’entorn de desenvolupament

Per desenvolupar contractes intel·ligents podem utilitzar entorns com ara truffle, que nos permite tener un ciclo de desarrollo sano. En este artículo usaremos directamente un editor online llamado Remix, que ens permetrà compilar, executar, analitzar i desplegar el contracte a través del nostre node local.

Accedirem a https://remix.ethereum.org/?#gist=505a93da7b10ed3438a0dcc68832b337 donde veremos el entorno Remix como se muestra a continuación, amb el contracte DCRL.sol precarregat des de gist.

 

A l’esquerra podem accedir a l’arbre del projecte, el compilador, l’accés al node per enviar transaccions i contractes i el gestor de complements. En el centre tenim el panell principal i sota, una terminal.

Podem editar el contracte, cada vegada que el desem s’autocompilarà mostrant els possibles errors de sintaxi.

Per desplegar el contracte accedirem a la pestanya “Deploy & Run Transactions”. Establirem com a entorn el nostre node local. Per a això seleccionem “Web3 Provider” a Environment. Deixarem el “Web3 Provider Endpoint” en el seu valor per defecte http://127.0.0.1:8545”. Després d’això sortiran els comptes del nostre node juntament amb el seu balanç a la secció “Account”. Seleccionarem el que tingui fons disponibles si en tenim més d’un.

Des de la consola del nostre node local desbloquejarem el compte per poder signar la transacció utilitzant el mètode unlockAccount de personal:

> personal.unlockAccount(eth.accounts[0])
Unlock account 0x673ce1bda1ca6a7d969b8f44e44d78ce9ef11691
Passphrase: 
true

 

A continuació premerem el botó “Deploy” des de l’entorn.

 

Desplegar un contracte és enviar una transacció a la xarxa Ethereum a través del nostre node local. El deploy no és instantani, la xarxa ha d’afegir la transacció a un bloc i arribar a un consens sobre la seva validesa. Una vegada arribat a l’acord, el nostre contracte està disponible globalment en una adreça.

Podem veure l’estat de les transaccions utilitzant un explorador de transaccions. Podem obtenir directament una url d’accés a la consola de l’entorn:

https://goerli.etherscan.io/tx/…

 

Una vegada desplegat, podem interactuar amb el contracte directament des del mateix entorn de desenvolupament, on sortiran els diferents mètodes disponibles al contracte.

 

Si introduïm una id en el mètode “has” i premem el botó del mètode, llançarem l’la crida i obtindrem el resultat esperat en el camp “decoded output” de la consola de l’entorn:

 

{
	"0": "bool: false"
}

 

Si ara utilitzem el mètode revoke, després de desbloquejar el compte, amb un paràmetre i consultem de nou el seu estat amb el mètode has, obtindrem true indicant que el certificat amb aquest SKID ha estat revocat.

Com a exercici demostrar que un altre compte no pot actualitzar la llista, crear usuari, etc.

 

La seguretat d’un contracte intel·ligent

Programar correctament un contracte intel·ligent és una feina especialment delicada. No només pels bugs que puguin tenir sinó pel seu propi disseny. El programari ha salvat moltes vegades la situació. Si la perseverance tiene un problema de software, se le enviará una actualización. Si tiene un problema de hardware, probablemente se arreglará también con una actualización de software. Estamos tan acostumbrados a las actualizaciones de software que olvidamos las consecuencias de un software que no se puede actualizar. Un contrato desplegado en la blockchain es inmutable.  Sin embargo, necesitamos cierto grado de mutabilidad para corregir posibles bugs o fer millores. 

Un contracte intel·ligent és “actualitzable” creant un nou contracte i transferint l’estat del vell contracte al nou. Però migrar l’estat pot ser car, l’adreça del contracte canviarà i el període de temps en el qual el vell i nou contracte coexisteixin és un gran problema.

L’alternativa és utilitzar un contracte (servidor intermediari o representant) per emmagatzemar l’estat i redirigir les crides a un altre contracte anomenat implementació que emmagatzema la lògica de negoci. D’aquesta manera, podem actualitzar la lògica de negoci sense haver de realitzar migracions més enllà d’indicar al servidor intermediari quina lògica utilitzar.

Projectes com OpenZeppelin

proporcionen un framework per simplificar la programació de contractes intel·ligents actualitzables.

Però cal advertir que reduir l’esforç de programar adequadament perquè el programari es pot actualitzar és un error de conseqüències molt greus. Y en el ámbito de los contratos inteligentes son habituales los robos o bloqueos irreversibles de fondos.

Un contracte intel·ligent ha d’utilitzar totes les eines al seu abast per garantir la seva seguretat. Incloent auditories, anàlisis estàtiques i dinàmiques de codi, tests…

Des del mateix entorn Remix podem utilitzar plugins que proporcionen anàlisis bàsiques de seguretat i estil. Per exemple, utilitzant Solint i Solidity Static Analysis obtenim els informes següents:

 

ls informes obtinguts són només això, informes amb suggeriments o aspectes a revisar. No seria la primera vegada que fer cas a cegues a aquestes anàlisis provoca un problema molt seriós.  Però tampoc no s’han d’ignorar els advertiments a la lleugera. Discutir cada advertiment amb altres persones competents i amb calma sol ser el més recomanable.

 

L’extensió per al certificat

Incorporarem l’adreça del contracte intel·ligent que acabem de desplegar als certificats mitjançant la definició d’una nova extensió.

L’estàndard ASN.1 s’utilitza per a la descripció d’estructures de dades de manera independent a la màquina. L’estructura dels certificats se sol expressar utilitzant aquesta sintaxi. La nostra extensió serà la següent:

DCRL  EXTENSION ::= {
SYNTAX             DCRLURIList
IDENTIFIED BY      id-dcrl }

DCRLURIList ::= SEQUENCE OF DCRLURI

DCRLURI ::= IA5String

 

Els OIDS són una seqüència de números separats per punt, jeràrquics que permeten identificar objectes. En aquesta extensió utilitzarem:

id-enterprise OBJECT IDENTIFIER ::= {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1)}
id-espublico  OBJECT IDENTIFIER::= {id-enterprise espublico(47281)}
id-esfirma-rd  OBJECT IDENTIFIER::= {espublico esfirma-rd(555)}
id-certs  OBJECT IDENTIFIER ::= {id-esfirma-rd certs(1)}
id-dcrl  OBJECT IDENTIFIER ::= {id-certs dcrl(1)}

 

Que corresponen a la taula següent

1.3.6.1.4.1.47281 Espublico
1.3.6.1.4.1.47281.555 ESFIRMA I+D+i Identifier
1.3.6.1.4.1.47281.555.1 x509Cert
1.3.6.1.4.1.47281.555.1.1 Decentralized Certificate Revocation Log (DCRL)

 

L’extensió contindrà una llista, una seqüència, d’identificadors de recursos uniforme (URI).

Cada URI definirà l’accés a un servei de consulta d’una blockchain.

Definirem l’URI d’accés al contracte intel·ligent DCRL de la xarxa com

dcrl:ethereum:

En el nostre cas, l’URI de consulta per al contracte intel·ligent que acabem de desplegar serà:

 

dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645 

 

La visualització de l’extensió DCRL

Per poder visualitzar l’extensió DCRL d’un certificat fàcilment afegirem la lògica al projecte XRAY-509. Afegim el processador de l’extensió DCRLProc,

public class DCRLProc extends BaseExtensionProc {


    @Override
    public Item processContent(Context ctx, Extension ext) throws IOException {
        Item out = new Item();
        if (ext.extnValue != null) {
            DCRLSequence i = new DCRLSequence();
            i.decode(ext.extnValue.from, ext.extnValue.value, true);
            int index = 0;
            for (BerIA5String name : i.seqOf) {
                out.prop(ItemHelper.index(index++),  new Item(new TaggedString("uri").addIndexTag(index), new TaggedString(String.valueOf(name)).addTag("type", "IA5String")));
            }
        }
        return out;
    }

}

fegirem el processament a la llista d’extensions conegudes en el mètode registerExtensions de la classe Context.

 

registerExtension("1.3.6.1.4.1.47281.555.1.1",new DCRLProc());

Com a exercici, fer el testing adequat a aquesta nova funcionalitat

 

L’emissió del certificat amb suport DCRL

Emetre un certificat digital consisteix a generar una parella de claus, crear una sol·licitud de signatura de certificat (CSR) i enviar el CSR a l’AC perquè generi el certificat.

Llançarem la nostra pròpia AC de proves basada en OpenSSL. Per a això crearem un certificat arrel.

$ openssl genrsa -out ca.key 2048
[..]
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:Aragon
Locality Name (eg, city) []:Zaragoza
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Espublico
Organizational Unit Name (eg, section) []:ESFIRMA I+D+i
Common Name (e.g. server FQDN or YOUR name) []:TEST CA  
Email Address []:

 

Utilitzant l’eina de visualització podem veure l’estructura detallada del certificat generat:

$ xray-cert ca.crt 
Version: 2 (v3)
SerialNumber: 9563599858331462912 (hex: 0x84b8bb66a9d2ad00, bits: 72)
Signature: 
    algo: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
    params: NULL
Issuer: 
    2.5.4.6 (countryName,C): ES (type: printableString)
    2.5.4.8 (stateOrProvinceName,ST): Aragon (type: utf8String)
    2.5.4.7 (localityName,L): Zaragoza (type: utf8String)
    2.5.4.10 (organizationName): Espublico (type: utf8String)
    2.5.4.11 (organizationalUnitName): ESFIRMA I+D+i (type: utf8String)
    2.5.4.3 (commonName,CN): TEST CA (type: utf8String)
Subject: 
    2.5.4.6 (countryName,C): ES (type: printableString)
    2.5.4.8 (stateOrProvinceName,ST): Aragon (type: utf8String)
    2.5.4.7 (localityName,L): Zaragoza (type: utf8String)
    2.5.4.10 (organizationName): Espublico (type: utf8String)
    2.5.4.11 (organizationalUnitName): ESFIRMA I+D+i (type: utf8String)
    2.5.4.3 (commonName,CN): TEST CA (type: utf8String)
Validity: 
    Duration: 1 month 2 days
    NotBefore: 2021-02-12T13:20:32Z
    NotAfter: 2021-03-14T13:20:32Z
[...]

 

Preparem la configuració de la CA per emetre certificats amb suport DCRL.

Creem el fitxer ca.conf:

[ ca ]
default_ca = test_ca

[ test_ca ]
serial = ./serial
database = ./index.txt
new_certs_dir = ./newcerts
certificate = ./ca.crt
private_key = ./ca.key
default_md = sha256
default_days = 365
policy = test_policy

[ test_policy ]
countryName = supplied
stateOrProvinceName = supplied
organizationName = supplied
organizationalUnitName = optional

i el fitxer cert.extensions.conf en el qual definirem l’extensió DCRL amb l’URI del nostre contracte intel·ligent.

basicConstraints=CA:FALSE
subjectAltName=@my_subject_alt_names
subjectKeyIdentifier = hash
1.3.6.1.4.1.47281.555.1.1=ASN1:SEQUENCE:DCRLExt

[DCRLExt]
uri=IA5STRING:dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645


[ my_subject_alt_names ]
DNS.1 = test.esfirma.com

 

Generem les claus i el CSR per al certificat final. Per a això afegirem un fitxer cert.conf amb les dades que ens agradaria que surtin al certificat:

[ req ]
default_bits = 2048
default_keyfile = cert.key
encrypt_key = no
default_md = sha256
prompt = no
utf8 = yes
distinguished_name = the_distinguished_name
req_extensions = the_extensions

[ the_distinguished_name ]
C = ES
ST = Aragon
L = Zaragoza
O  = Espublico
OU = Esfirma I+D+i

[ the_extensions ]
basicConstraints=CA:FALSE
subjectAltName=@the_subject_alt_names
subjectKeyIdentifier = hash

[ the_subject_alt_names ]
DNS.1 = test.esfirma.com

 

Creem el CSR per enviar-lo a l’AC

$ openssl req -new -out cert.csr -config cert.conf

 

L’AC verificarà la informació continguda en el CSR, validarà la identitat del sol·licitant i emetrà un certificat.

$ openssl ca -config ca.conf -out cert.crt -extfile cert.extensions.conf -in cert.csr

 

El nou certificat contindrà una extensió DCRL.

$ xray-cert cert.crt 
[...]
Issuer: 
    2.5.4.6 (countryName,C): ES (type: printableString)
    2.5.4.8 (stateOrProvinceName,ST): Aragon (type: utf8String)
    2.5.4.7 (localityName,L): Zaragoza (type: utf8String)
    2.5.4.10 (organizationName): Espublico (type: utf8String)
    2.5.4.11 (organizationalUnitName): ESFIRMA I+D+i (type: utf8String)
    2.5.4.3 (commonName,CN): TEST CA (type: utf8String)
Subject: 
    2.5.4.6 (countryName,C): ES (type: printableString)
    2.5.4.8 (stateOrProvinceName,ST): Aragon (type: utf8String)
    2.5.4.10 (organizationName): Espublico (type: utf8String)
    2.5.4.11 (organizationalUnitName): Esfirma I+D+i (type: utf8String)
[...]
Extensions: 
    2.5.29.19 (Basic constraints)
        None
    2.5.29.17 (Subject alternative name)
        DNSName: test.esfirma.com (type: IA5String)
    2.5.29.14 (Subject key identifier)
        Identifier: e2:a4:1b:59:70:00:ac:93:93:8b:4e:1d:88:cc:77:3e:
                    6c:69:01:f4
    1.3.6.1.4.1.47281.555.1.1 (DCRL - Decentralized Certificate Revocation Log)
        [0] uri: dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645 (type: IA5String)
[...]


L’eina per consultar la DCRL
Afegirem al projecte XRAY dues noves eines, una per consultar l’estat de revocació d’un certificat mitjançant la consulta de l’extensió DCRL i una altra per revocar el certificat.
Per a això afegim a pom.xml la dependència web3j. Una llibreria lleugera i modular per interactuar amb contractes intel·ligents a la xarxa Ethereum .


org.web3j
core
5.0.0

 
 
Per generar un wrapper a partir del contracte intel·ligent afegim al pom el següent plugin.
 
           
               org.web3j
                web3j-maven-plugin
                4.6.5
               
                    com.k10ud.xray509.blockchain.model
                    src/main/java
                    true
                    java,bin
                   
                        src/main/resources/sol
                       
                            **/*.sol
                       
                   
               
           
                   
               
 
Generem el wrapper amb l’ordre
 
mvn web3j:generate-sources
 
Definirem la nostra ordre xray-dcrs que tan sols necessitarà com a paràmetres el certificat per consultar. Opcionalment, es pot especificar l’adreça del servei JSON-RPC del node client d’Ethereum que volem utilitzar, sent el node local el defecte,
 
   @CommandLine.Command(name = "xray-dcrs",
            header = "xray-dcrs 0.0.1",
            showDefaultValues = true,
            description = "x509 decentralized certificate revocation store"
    )
    public static class Args extends CommonArgs {
        @CommandLine.Parameters(arity = "1", paramLabel = "SOURCE", description = "X509Certificate with dcrl extension")
        private String[] inputFile;
        @CommandLine.Option(names = {"--http-service"}, description = "Ethereum JSON-RPC Service Address")
        public String httpService;
    }
 
[...]
 
  String contractAdddress = contractURI.substring(DCRL_ETHEREUM.length());
            Web3j web3 = Web3j.build(new HttpService(app.httpService != null ? app.httpService : "http://localhost:8545/"));
            Credentials credentials = Credentials.create("00000000000000000000000000000000");
            DCRL contract = DCRL.load(contractAdddress, web3, credentials, new DefaultGasProvider());
            boolean revoked;
            try {
                revoked = contract.has(new BigInteger(1, contracts.skid)).send();
                entry.prop("revoked", revoked);
            } catch (Exception e) {
                entry.prop("error", "smartc entry call: " + Exceptions.getSmartExceptionMessage(e));
            }
 
Extraiem la llista d’URI de l’extensió del certificat utilitzant la consulta.
 
MATCH 
Extensions/1.3.6.1.4.1.47281.555.1.1/$contracts:=uri,
Extensions/2.5.29.14/$skid:=Identifier 
RETURN $contracts, $skid
 
Afegim al pom l’ordre
 
 
com.k10ud.cli.XrayDCRL
xray-dcrl
 
 
Compilem el projecte.
 
mvn package
 
I ho provem amb el nostre certificat de proves.
 
$ xray-dcrl cert.crt 
skid: E2A41B597000AC93938B4E1D88CC773E6C6901F4
dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645
    revoked: false
 
L’ordre ha analitzat el certificat, determinat el seu SKID, extret de la seva extensió DCRL l’URI de consulta i connectat amb el node local d’Ethereum per verificar l’estat de revocació del certificat.
 
L’eina per revocar un certificat DCRL
L’eina llegirà un certificat, extraurà l’URI de consulta de la DCRL i crearà una transacció per establir el certificat com revocat. L’ordre necessitarà el certificat a revocar i la localització de la wallet per signar la transacció. Opcionalment, podem establir el límit de gas i el seu preu per a l’execució de la transacció.
 
    @CommandLine.Command(name = "xray-dcrl-publish",
            header = "xray-dcrl-publish 0.0.1",
            showDefaultValues = true,
            description = "Decentralized Certificate Revocation Log DCRL publisher"
    )
    public static class Args {
        @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true,
                description = "Displays this help message and quits.")
        public boolean helpRequested = false;
        public Context context;
 
 
        @CommandLine.Parameters(arity = "1", paramLabel = "SOURCE", description = "X509Certificate with dcrl extension")
        private String[] inputFile;
        @CommandLine.Option(names = {"--wallet-pass"}, description = "Wallet password... ONLY FOR TESTING")
        public String wpass;
        @CommandLine.Option(required = true, names = {"--wallet-source"}, description = "Wallet file source")
        public String wsource;
        @CommandLine.Option(names = {"--gas-price"}, description = "Tx Gas Price, -1 auto estimate")
        public BigInteger gasPrice = BigInteger.valueOf(-1);
        @CommandLine.Option(names = {"--gas-limit"}, description = "Tx Gas Limit")
        public BigInteger gasLimit = BigInteger.valueOf(100_000);
        @CommandLine.Option(names = {"--http-service"}, description = "Ethereum JSON-RPC Service Address")
        public String httpService;
    }
 

L’ordre carregarà la wallet a partir dels paràmetres.

 
                Credentials credentials;
                try {
                    credentials = WalletUtils.loadCredentials(app.wpass != null ? app.wpass : "", app.wsource);
                } catch (Exception e) {
                    log("error", "credentials: " + Exceptions.getSmartExceptionMessage(e));
                    return;
                }
  
[...]              
          price = web3.ethGasPrice().send().getGasPrice();
     
[...]
           DCRL contract = DCRL.load(contractAdddress, web3, credentials, new StaticGasProvider(price, app.gasLimit));
                    TransactionReceipt tx = contract.revoke(new BigInteger(1, contracts.skid)).send();
Una vez añadido el comando al pom y empaquetado el proyecto procederemos a recovar el certificado de prueba. El fichero de la wallet estará  en ~/.ethereum/goerli/keystore
 
$ xray-dcrl-revoke --wallet-source wallet.file cert.crt 
skid: E2A41B597000AC93938B4E1D88CC773E6C6901F4
gas_estimated_price: 20000000000
status: 0x1
from: 0x673ce1bda1ca6a7d969b8f44e44d78ce9ef11691
to: 0xd807991602ec9269e233e54188a5b9a6ed904645
contract_address: null
hash: 0x7b2be3df8dedb966fefb3c207eae0cde610b2b04abf28f2a315209d57cf76ff4
number: 4270979
used: 43326
cumulative: 94316
revert_reason: null
root: null
hash: 0x8f0d733160ebb285e6e41b9a4f749bc6fc2f82bc493eddbf50eabd5a5650f79b
index: 1
dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645: revoked: true
 

Després d’uns instants la transacció serà incorporada a un bloc de la xarxa Ethereum de proves. Podem consultar l’estat de la transacció a etherscan:

https://goerli.etherscan.io/tx/

Si tornem a consultar l’estat del certificat, obtindrem la marca de revocat

 
$ xray-dcrl cert.crt 
skid: E2A41B597000AC93938B4E1D88CC773E6C6901F4
dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645
    revoked: true
 
 
El certificat complet
El certificat de prova que hem utilitzat no compleix els requisits mínims necessaris de les bones pràctiques de certificació . A continuació es mostra en detall l’estructura completa d’un certificat real, en el qual la informació de punts de consulta de revocació descentralitzada conviu amb els mecanismes tradicionals.
 
Version: 2 (v3)
SerialNumber: 161622362496637328561239031025230663875 (hex: 0x799755b2edcbf3e576674490214fd0c3, bits: 128)
Signature: 
    algo: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
    params: NULL
Issuer: 
    2.5.4.3 (commonName,CN): ESFIRMA DEV AAPP (type: utf8String)
Subject: 
    2.5.4.97 (organizationIdentifier): VATES-TEST (type: utf8String)
    2.5.4.6 (countryName,C): ES (type: printableString)
    2.5.4.7 (localityName,L): ZARAGOZA (type: utf8String)
    2.5.4.10 (organizationName): PRUEBA-TEST (type: utf8String)
    2.5.4.5 (serialNumber,SN): TEST (type: printableString)
    2.5.4.15 (businessCategory): Government Entity (type: utf8String)
    1.3.6.1.4.1.311.60.2.1.3 (jurisdictionOfIncorporationCountryName): ES (type: printableString)
Validity: 
    Duration: 1 year 25 days
    NotBefore: 2021-02-12T12:16:32Z
    NotAfter: 2022-03-09T12:16:32Z
SubjectPublicKeyInfo: 
    Algorithm: 
        algo: 1.2.840.113549.1.1.1 (RSA)
        params: NULL
    PublicKey: 
   [...]
    Key length: 2048 (0x800)
   [...]
Extensions: 
    2.5.29.32 (Certificate policies)
        Policies: 
            2.16.724.1.3.5.5.2 (MPR SEDE ELECTRONICA (Nivel Medio,Sustancial))
            0.4.0.194112.1.4 (QCP-w: certificate policy for European Union (EU) qualified website authentication certificates )
            1.3.6.1.4.1.47281.1.4.2 (esFIRMA Sede electrónica AAPP - MEDIO en Software - EV): 
                1.3.6.1.5.5.7.2.1 (CPS)
                    URI: https://www-esfirma.g3stiona.com/doc-pki/ (type: IA5String)
                1.3.6.1.5.5.7.2.2 (User Notice)
                    ExplicitText: Certificado cualificado de sede electrónica de PRUEBA-TEST nivel medio. Consulte https://www-esfirma.g3stiona.com/doc-pki/ (type: utf8String)
            2.23.140.1.1 (Extended Validation (EV) guidelines certificate policy)
    2.5.29.14 (Subject key identifier)
        Identifier: 03:3f:07:0b:b8:46:69:db:a8:01:97:c8:e9:a5:8c:6e:
                    3f:41:5a:12
    2.5.29.35 (Authority key identifier)
        Identifier: f4:76:84:70:6c:94:96:9a:f9:d8:26:74:94:ec:2e:d9:
                    34:5a:db:35
    2.5.29.19 (Basic constraints)
        None
    2.5.29.15 (Key usage): 
        Critical
        0 (DigitalSignature)
        2 (KeyEncipherment)
    2.5.29.37 (Extended key usage)
        1.3.6.1.5.5.7.3.1 (serverAuth)
    2.5.29.31 (Revocation List distribution points): 
        DistributionPoint
            Name
                FullName
                    [0] uri: http://crls1-esfirma.g3stiona.com/acaapp/acaapp.crl (type: IA5String)
        DistributionPoint
            Name
                FullName
                    [0] uri: http://crls2-esfirma.g3stiona.com/acaapp/acaapp.crl (type: IA5String)
    1.3.6.1.5.5.7.1.1 (Authority Information Access): 
        AccessDescription: 
            Method: 1.3.6.1.5.5.7.48.1 (ocsp)
            Location
                uri: http://ocsp1-esfirma.g3stiona.com/acaapp/ (type: IA5String)
        AccessDescription: 
            Method: 1.3.6.1.5.5.7.48.1 (ocsp)
            Location
                uri: http://ocsp2-esfirma.g3stiona.com/acaapp/ (type: IA5String)
        AccessDescription: 
            Method: 1.3.6.1.5.5.7.48.2 (caIssuers)
            Location
                uri: http://www-esfirma.g3stiona.com/doc-pki/acaapp.crt (type: IA5String)
    1.3.6.1.4.1.47281.555.1.1 (DCRL - Decentralized Certificate Revocation Log)
        uri: dcrl:ethereum:0xd807991602EC9269e233e54188a5b9A6Ed904645 (type: IA5String)
    2.5.29.17 (Subject alternative name)
        DNSName: good2.testing.esfirma.com (type: IA5String)
    1.3.6.1.5.5.7.1.3 (QcStatements): 
        0.4.0.1862.1.1 (QcCompliance)
        0.4.0.1862.1.6 (QcType)
            0.4.0.1862.1.6.3 (web)
        0.4.0.1862.1.3 (QcRetentionPeriod)
            Years: 15 (0xf)
        0.4.0.1862.1.5 (QcPDS): 
            Location: 
                lang: en (type: PrintableString)
                url: https://www-esfirma.g3stiona.com/doc-pki/PDS/SE2-MEDIO-SOFT-EN/ (type: IA5String)
            Location: 
                lang: es (type: PrintableString)
                url: https://www-esfirma.g3stiona.com/doc-pki/PDS/SE2-MEDIO-SOFT-ES/ (type: IA5String)
        1.3.6.1.5.5.7.11.2 (id-qcs-pkixQCSyntax-v2)
            keyIdentifier: 0.4.0.194121.1.2 (Id-etsi-qcs-SemanticsId-Legal)
    2.23.140.3.1 (CABForum OrganizationIdentifier): 
        SchemeIdentifier: VAT (type: printableString)
        Country: ES (type: printableString)
        Reference: TEST (type: utf8String))
 [...]
 
 
Las conclusions

La confiança és la clau. Per al sistema mostrat en aquest article confiem en la llista de certificats arrel que ve preconfigurada amb el navegador, als servidors DNS que tenim configurats per resoldre l’adreça IP d’un nom de domini. Així com els nodes inicials que ens permeten arrencar la xarxa d’Ethereum.

En general, és millor evitar sistemes centralitzats que són més vulnerables que els seus equivalents descentralitzats. Les noves tecnologies descentralitzades reemplaçaran inevitablement a poc a poc les velles estructures.

La redescentralització ha començat!
 
 
Artículos Relacionados:
Autor
David Castañon
David Castañon

Ver todos sus artículos

Etiquetes
Subscriu-te al nostre butlletí i no et perdis cap article

Pots donar-te de baixa en qualsevol moment fent clic a l'enllaç al peu de pàgina dels nostres correus electrònics. Utilitzem Mailchimp com a plataforma de màrqueting. En fer clic a continuació per registrar-vos, accepteu que la vostra informació serà transferida a Mailchimp perquè la processi. Per prendre més informació sobre les pràctiques de privadesa de Mailchimp.



Política de cookies

La teva privadesa és important per a nosaltres

Utilitzem galetes de tercers per mesurar i millorar la seva experiència. Acceptes?

Cookies essencials
Actives sempre
Cookies analítiques

ACCEPTAR SELECCIONAT



Més informació sobre cookies

pujar