Caso práctico: identidad digital
Clase 2 de 11 • Curso de Casos de Uso de Smart Contracts
Resumen
Los contratos inteligentes o smart contracts son cadenas de bloques que se ejecutan cuando se cierra un acuerdo que cumple con ciertas condiciones establecidas, entre dos o más partes, y no necesita de una entidad o un tercero para ser aprobado. La identidad digital de una persona o una empresa puede ser representada por uno o más contratos inteligentes.
Autenticación vs. Autorización
Autenticación y autorización son dos palabras similares que podemos confundir, pero que en realidad no son sinónimos ni guardan relación.
- Autenticación: demostrar que soy, quien digo que soy, para acceder a un lugar.
- Autorización: una vez que demuestre quien soy y puedo acceder, tengo que demostrar qué permisos o accesos tengo para acceder en determinado lugar.
La Autenticación nos identifica y la Autorización nos da los privilegio o no para llegar hasta determinado punto de un sistema o lugar.
Autenticación y Autorización en Blockchain
En una Blockchain, a través de la dirección de una wallet, podemos determinar quién es el que realiza la transacción, puesto que esta solo puede ser firmada con una clave privada de la cuenta. La criptografía es el poderoso mecanismo que permite asegurar la identidad de una cuenta y que nadie más pueda falsificarla.
Autenticación de usuarios
Podemos representar y validar la autenticación de un usuario de forma muy sencilla en un contrato inteligente.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Authentication {
mapping(address => bool) public users;
function authenticate() public {
users[msg.sender] = true;
}
}
Guardamos en un mapping
una relación entre una dirección y un booleano. Si una cuenta se autenticó previamente, podremos comprobarlo.
Lo importante aquí es que solo el dueño de la cuenta pueda poner en true
el booleano que le corresponde a su dirección llamando a la función authenticate()
.
Autorización de usuarios
La autorización siempre es algo más compleja. Requiere llevar un registro de qué puede y qué no puede hacer un usuario.
contract Identity {
struct BasicInfo {
string name;
string email;
}
struct PersonalInfo {
uint256 salary;
string _address;
}
enum UserType {
Basic,
Personal
}
error UserUnauthorized(address user, UserType userType);
// Variables para guardar información de la cuenta
BasicInfo private basicInfo;
PersonalInfo private personalInfo;
address private owner;
// Mapping para otorgar permisos de lectura a otras cuentas
mapping(address => bool) private basicUsers;
mapping(address => bool) private personalUsers;
constructor(string memory name, string memory email, uint256 salary, string memory _address) {
basicInfo = BasicInfo(name, email);
personalInfo = PersonalInfo(salary, _address);
owner = msg.sender;
}
// Verificador de Autorización del usuario
modifier authorizeUser(UserType userType) {
if (msg.sender == owner || personalUsers[msg.sender]) {
_;
} else if (userType == UserType.Basic && basicUsers[msg.sender]) {
_;
} else {
revert UserUnauthorized(msg.sender, userType);
}
}
// Solo el owner puede otorgar permisos a otras cuentas
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can authorize users");
_;
}
// Otorgamos permisos de lectura a otra cuenta
function registerUser(UserType userType, address user) public onlyOwner {
if (userType == UserType.Basic) {
basicUsers[user] = true;
} else if (userType == UserType.Personal) {
personalUsers[user] = true;
}
}
function getBasicInfo() public view authorizeUser(UserType.Basic) returns (BasicInfo memory) {
return basicInfo;
}
function getPersonalInfo() public view authorizeUser(UserType.Personal) returns (PersonalInfo memory) {
return personalInfo;
}
}
El contrato anterior, cumple con algunas pautas que permiten asegurar los datos de un usuario y que solo él pueda decidir qué hacer con estos.
- Solo la dirección que crea la instancia del contrato tiene permisos de owner.
- Solo el owner puede otorgar permisos a otras cuentas para que vean su información.
- Otras cuentas pueden ver la información del owner, solo si este lo permitió previamente.
Consejos de seguridad para smart contracts
Guardar datos sensibles en un contrato inteligente requiere de un paso extra: encriptación. Producir variables privadas no basta para que nadie pueda acceder a ellos y existen algunos hacks para lograr obtener datos de una variable privada.
Esto no necesariamente es un bug o un problema, ya que todo en Blockchain debe ser transparente. Nada puede ocultarse realmente. Es por esto que se requieren algoritmos de encriptación para asegurar esos datos privados y que solo el owner del contrato conozca la manera de desencriptar los mismos.
Desafíos de la Autorización
De aquí se desprenden al menos dos retos para ti. Por un lado, la Autenticación y Autorización deben trabajar juntos. Un usuario no debería tener permisos para nada si previamente no fue autenticado. ¿Cómo podrías relacionar ambos conceptos en un contrato inteligente?
Por otro lado, volviendo al tema de la privacidad de datos, es realmente un desafió que los datos sean privados y que solo sean leídos por cuentas autorizadas. No es una solución que las variables sean privadas, tampoco el envío de contraseñas porque toda información es pública en la transacción.
No olvidemos que el código de un contrato inteligente también es público, por lo tanto, no nos sirve crear un superalgoritmo de encriptación o utilizar uno ya existente, porque el mismo será visible.
- Entonces, ¿Blockchain no sirve para guardar datos sensibles? Como ya hemos dicho, es todo un desafío técnico y, como desarrolladores de software, debemos encontrar los caminos, investigar y leer mucho al respecto.
Posibles soluciones son la encriptación/desencriptación de los datos fuera de la Blockchain para enviar y recibir los mismos ya encriptados. Comparación de hashes para verificar los datos o utilizando servicios off-chain como ChainLink.
El ecosistema de Ethereum sigue creciendo y las soluciones existen o existirán. Continuar aprendiendo al respecto nos hará como profesionales en Blockchain y contratos inteligentes poder encontrar las mismas o incluso proponerlas.
Contribución creada por: Kevin Fiorentino.