Una aplicación descentralizada para notarizar y verificar documentos PDF en la blockchain de Ethereum usando firmas EIP-712.
Esta dApp te permite demostrar criptográficamente tres hechos clave sobre un documento:
- El documento existió - El hash se almacena on-chain con una marca de tiempo
- Fue firmado por una billetera específica - La dirección del firmante queda registrada
- En una fecha determinada - La marca de tiempo del bloque proporciona prueba de cuándo fue notarizado
La integridad del contenido está garantizada porque cualquier modificación al documento resultaría en un hash diferente.
- Notarizar Documentos: Sube un PDF, fírmalo usando EIP-712 y almacena su hash on-chain
- Verificar Documentos: Verifica si un documento ha sido notarizado y ve quién lo firmó y cuándo
- Firmas EIP-712: Usa firmado de datos estructurados para mejor seguridad y UX
- Integración con MetaMask: Conexión de billetera sin problemas
- Sepolia Testnet: Desplegado en la testnet Sepolia de Ethereum
- Next.js 15 con App Router
- TypeScript
- Tailwind CSS
- ethers.js v6
- Solidity 0.8.20 (Contrato Inteligente)
- OpenZeppelin Contracts (implementación EIP-712)
El contrato está desplegado en la testnet Sepolia. Puedes encontrar el contrato en:
// lib/contract.ts
export const CONTRACT_ADDRESS = "0xYOUR_CONTRACT_ADDRESS_HERE";notarize(bytes32 docHash, bytes signature): Notariza un documento con una firma EIP-712documents(bytes32 docHash): Ver detalles de notarización para un hash de documento
- Node.js 18+
- Extensión de navegador MetaMask
- ETH de la testnet Sepolia (obtener desde faucet de Sepolia)
- Clonar el repositorio:
git clone <tu-url-del-repo>
cd document-notary- Instalar dependencias:
npm install- Actualizar la dirección del contrato:
Edita lib/contract.ts y reemplaza CONTRACT_ADDRESS con la dirección de tu contrato desplegado:
export const CONTRACT_ADDRESS = "0xTuDireccionDelContrato";- Ejecutar el servidor de desarrollo:
npm run dev- Abre http://localhost:3000 en tu navegador
- Haz clic en "Conectar Billetera" para conectar tu billetera MetaMask
- Asegúrate de estar en la red Sepolia (la dApp te pedirá cambiar si es necesario)
- Ve a la pestaña "Notarizar Documento"
- Sube un archivo PDF
- La dApp generará automáticamente el hash del archivo usando keccak256
- Haz clic en "Firmar con EIP-712" para firmar el hash con tu billetera
- Haz clic en "Notarizar en Blockchain" para enviar la transacción
- Espera a que la transacción se confirme en Sepolia
- Ve a la pestaña "Verificar Documento"
- Sube el archivo PDF que deseas verificar
- Haz clic en "Verificar en Blockchain"
- Si el documento ha sido notarizado, verás:
- El hash del documento
- Quién lo firmó (dirección de billetera)
- Cuándo fue notarizado (marca de tiempo)
La dApp usa EIP-712 (Firmado de Datos Estructurados Tipados) que proporciona:
- Mejor UX: Los usuarios pueden ver qué están firmando
- Mejor seguridad: Previene la reutilización de firmas en diferentes contratos/cadenas
- Formato estándar: Compatible con MetaMask y otras billeteras
El dominio de firmado:
{
name: "DocumentNotary",
version: "1",
chainId: 11155111, // Sepolia
verifyingContract: CONTRACT_ADDRESS
}Los datos tipados:
{
Document: [
{ name: "hash", type: "bytes32" }
]
}- El archivo PDF se lee como un ArrayBuffer
- El contenido se convierte a un Uint8Array
- El hash keccak256 se calcula usando ethers.js
- Este hash se usa para firmar y almacenar on-chain
- El PDF subido se hashea usando el mismo método
- El hash se usa para consultar el contrato inteligente
- Si se encuentra, el contrato devuelve la dirección del firmante y la marca de tiempo
- El usuario puede verificar la integridad comparando los hashes
document-notary/
├── app/
│ ├── page.tsx # Página principal con pestañas
│ ├── layout.tsx # Layout raíz
│ └── globals.css # Estilos globales
├── components/
│ ├── WalletConnect.tsx # Componente de conexión de billetera
│ ├── NotarizeDocument.tsx # UI de notarización de documentos
│ └── VerifyDocument.tsx # UI de verificación de documentos
├── hooks/
│ └── useWallet.ts # Hook de conexión de billetera
├── lib/
│ ├── contract.ts # ABI y configuración del contrato
│ └── utils.ts # Funciones de utilidad
└── README.md
- La dApp solo almacena hashes de documentos, no los documentos reales
- Los documentos nunca se suben a la blockchain o a ningún servidor
- Todo el hashing ocurre del lado del cliente en el navegador
- Las firmas EIP-712 aseguran que la firma no puede ser repetida en diferentes contratos o cadenas
- El contrato previene la re-notarización del mismo documento
- Solo se soportan archivos PDF
- El hashing de archivos se hace completamente en el navegador (puede ser lento para archivos grandes)
- Una vez notarizado, un hash de documento no puede ser actualizado o eliminado
- La verificación requiere exactamente el mismo archivo (incluso un cambio de 1 bit producirá un hash diferente)
MIT
¡Las pull requests son bienvenidas! Por favor abre un issue primero para discutir cualquier cambio importante.