Site principal
This commit is contained in:
commit
1c86a654dc
3 changed files with 819 additions and 0 deletions
64
certificates.js
Normal file
64
certificates.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// ==========================================
|
||||
// CONFIGURAÇÃO DE CERTIFICADOS E CRLS
|
||||
// ==========================================
|
||||
// Instruções:
|
||||
// Cole o texto puro (formato PEM) entre as crases (` `).
|
||||
// O site cuidará de transformar isso em arquivos .crt, .pem e .crl para download.
|
||||
|
||||
const pkiData = {
|
||||
certificates: {
|
||||
// --- CADEIA INTERNA ---
|
||||
internal_root: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_O_SEU_ROOT_INTERNO_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
internal_inter: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_INTERNA_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
internal_bundle: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_INTERNA_AQUI...
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_O_SEU_ROOT_INTERNO_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
// --- CADEIA EXTERNA ---
|
||||
external_root: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_O_SEU_ROOT_EXTERNO_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
external_web: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_WEB_EXTERNA_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
external_web_bundle: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_WEB_EXTERNA_AQUI...
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_O_SEU_ROOT_EXTERNO_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
external_infra: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_INFRA_EXTERNA_AQUI...
|
||||
-----END CERTIFICATE-----`,
|
||||
|
||||
external_infra_bundle: `-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_A_SUA_ICA_INFRA_EXTERNA_AQUI...
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MII_COLE_O_SEU_ROOT_EXTERNO_AQUI...
|
||||
-----END CERTIFICATE-----`
|
||||
},
|
||||
|
||||
crls: {
|
||||
// --- LISTAS DE REVOGAÇÃO (CRL) ---
|
||||
internal: `-----BEGIN X509 CRL-----
|
||||
MII_COLE_A_SUA_CRL_INTERNA_AQUI...
|
||||
-----END X509 CRL-----`,
|
||||
|
||||
external: `-----BEGIN X509 CRL-----
|
||||
MII_COLE_A_SUA_CRL_EXTERNA_AQUI...
|
||||
-----END X509 CRL-----`
|
||||
}
|
||||
};
|
||||
741
index.html
Normal file
741
index.html
Normal file
|
|
@ -0,0 +1,741 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="pt-BR" class="scroll-smooth">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Linkwave Private Root CA | Repositório Oficial</title>
|
||||
<link rel="icon" type="image/png" href="https://ca.openwave.net.br/assets/openwaveca.png">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- Atualizado para versão 6.4.0 para suportar o ícone building-shield -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
|
||||
<!-- Biblioteca Criptográfica para o Decodificador -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.9.0/jsrsasign-all-min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: #050505; /* Ultra dark background */
|
||||
color: #e5e5e5;
|
||||
overflow-x: hidden; /* Evita quebra de layout no mobile */
|
||||
overscroll-behavior-y: none; /* Previne o lag de rebote no mobile */
|
||||
}
|
||||
.glass-panel {
|
||||
background: rgba(10, 10, 10, 0.85); /* Dark glass */
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid rgba(50, 50, 50, 0.5);
|
||||
/* Aceleração de Hardware para matar o lag do blur no scroll */
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
will-change: transform, backdrop-filter;
|
||||
}
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #0a0a0a;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #333;
|
||||
border-radius: 4px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #3b82f6;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Navigation Active State */
|
||||
.nav-link.active {
|
||||
color: #ffffff;
|
||||
border-bottom: 2px solid #3b82f6;
|
||||
}
|
||||
|
||||
/* Page Transitions */
|
||||
.page-section {
|
||||
animation: fadeIn 0.4s ease-out;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* Toast Animation */
|
||||
@keyframes slideIn {
|
||||
from { transform: translateY(100%); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
.toast {
|
||||
animation: slideIn 0.3s ease-out forwards;
|
||||
}
|
||||
.toast.hiding {
|
||||
animation: fadeOut 0.3s ease-in forwards;
|
||||
}
|
||||
|
||||
/* Result Animation */
|
||||
.result-box {
|
||||
animation: expandBox 0.3s ease-out forwards;
|
||||
}
|
||||
@keyframes expandBox {
|
||||
from { opacity: 0; transform: scale(0.95); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Checksum Style */
|
||||
.checksum-box {
|
||||
font-family: 'Monaco', 'Consolas', monospace;
|
||||
font-size: 0.65rem;
|
||||
color: #6b7280;
|
||||
background: #1f2937;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
margin-top: 8px;
|
||||
word-break: break-all;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.checksum-box:hover {
|
||||
color: #9ca3af;
|
||||
background: #374151;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="antialiased min-h-screen flex flex-col">
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="fixed w-full z-50 glass-panel">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center h-16">
|
||||
<div class="flex items-center gap-3 cursor-pointer shrink-0 group" onclick="navigateTo('home')">
|
||||
<!-- LOGO AUMENTADO -->
|
||||
<img src="https://ca.openwave.net.br/assets/linkwavepki.png"
|
||||
alt="Linkwave PKI Logo"
|
||||
class="h-10 md:h-12 w-auto object-contain transition-transform duration-300 group-hover:scale-105">
|
||||
<div class="h-5 w-px bg-gray-700 hidden sm:block"></div>
|
||||
<span class="font-display font-bold text-white text-sm md:text-base hidden sm:block tracking-wide group-hover:text-blue-500 transition-colors">Autoridade de Cert.</span>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Menu -->
|
||||
<div class="hidden md:flex space-x-8 text-sm font-medium text-gray-400 h-16 items-center">
|
||||
<button onclick="navigateTo('home')" id="nav-home" class="nav-link h-full border-b-2 border-transparent hover:text-white transition-all px-1">Repositório</button>
|
||||
<button onclick="navigateTo('tools')" id="nav-tools" class="nav-link h-full border-b-2 border-transparent hover:text-white transition-all px-1">Ferramentas</button>
|
||||
<button onclick="navigateTo('policies')" id="nav-policies" class="nav-link h-full border-b-2 border-transparent hover:text-white transition-all px-1">Políticas (CPS)</button>
|
||||
<button onclick="navigateTo('crl')" id="nav-crl" class="nav-link h-full border-b-2 border-transparent hover:text-white transition-all px-1">Revogação (CRL)</button>
|
||||
</div>
|
||||
|
||||
<!-- Ações Direitas (Botão Voltar Hub + Menu Mobile) -->
|
||||
<div class="flex items-center gap-3 shrink-0">
|
||||
<a href="https://openwave.net.br" class="text-[10px] sm:text-xs font-bold text-gray-400 hover:text-white transition-colors flex items-center gap-2 bg-[#111] hover:bg-[#222] px-3 sm:px-4 py-2 rounded-lg border border-gray-800">
|
||||
<i class="fa-solid fa-arrow-left"></i> <span class="hidden sm:inline">Voltar ao Hub</span>
|
||||
</a>
|
||||
|
||||
<!-- Mobile Menu Button -->
|
||||
<div class="md:hidden flex items-center">
|
||||
<button onclick="document.getElementById('mobile-menu').classList.toggle('hidden')" class="text-gray-300 hover:text-white">
|
||||
<i class="fa-solid fa-bars text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu Dropdown -->
|
||||
<div id="mobile-menu" class="hidden md:hidden bg-[#0a0a0a] border-b border-gray-800">
|
||||
<div class="px-2 pt-2 pb-3 space-y-1 sm:px-3">
|
||||
<button onclick="navigateTo('home'); document.getElementById('mobile-menu').classList.add('hidden')" class="block w-full text-left px-3 py-2 text-base font-medium text-gray-300 hover:text-white hover:bg-gray-800 rounded-md">Repositório</button>
|
||||
<button onclick="navigateTo('tools'); document.getElementById('mobile-menu').classList.add('hidden')" class="block w-full text-left px-3 py-2 text-base font-medium text-gray-300 hover:text-white hover:bg-gray-800 rounded-md">Ferramentas</button>
|
||||
<button onclick="navigateTo('policies'); document.getElementById('mobile-menu').classList.add('hidden')" class="block w-full text-left px-3 py-2 text-base font-medium text-gray-300 hover:text-white hover:bg-gray-800 rounded-md">Políticas (CPS)</button>
|
||||
<button onclick="navigateTo('crl'); document.getElementById('mobile-menu').classList.add('hidden')" class="block w-full text-left px-3 py-2 text-base font-medium text-gray-300 hover:text-white hover:bg-gray-800 rounded-md">Revogação (CRL)</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- CONTENT CONTAINER -->
|
||||
<main class="flex-grow pt-24 pb-16 px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto w-full">
|
||||
|
||||
<!-- PAGE: HOME (REPOSITORY) -->
|
||||
<div id="page-home" class="page-section">
|
||||
<div class="max-w-4xl mx-auto text-center mb-16 pt-8">
|
||||
<div class="inline-flex items-center px-3 py-1 rounded-full bg-gray-900 border border-gray-800 text-xs font-medium text-gray-400 mb-6">
|
||||
<span class="w-2 h-2 bg-emerald-500 rounded-full mr-2 shadow-[0_0_8px_rgba(16,185,129,0.5)]"></span>
|
||||
Sistemas Operacionais
|
||||
</div>
|
||||
<h1 class="text-4xl md:text-6xl font-bold tracking-tight mb-6 text-white">
|
||||
Hierarquia de Confiança <br class="hidden md:block"/><span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-indigo-500">Linkwave Connect.</span>
|
||||
</h1>
|
||||
<p class="text-lg md:text-xl text-gray-500 max-w-2xl mx-auto leading-relaxed">
|
||||
Selecione abaixo o certificado raiz adequado para sua necessidade.
|
||||
Disponibilizamos ambientes distintos para operações internas e clientes externos.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- DUAL CERTIFICATE GRID -->
|
||||
<div id="download-area" class="grid lg:grid-cols-2 gap-8 mb-16">
|
||||
|
||||
<!-- CARD 1: INTERNAL ROOT -->
|
||||
<div class="bg-[#111111] rounded-2xl shadow-2xl border border-gray-800 overflow-hidden relative group hover:border-blue-900/50 transition-all">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span class="bg-blue-900/20 border border-blue-900/50 text-blue-400 text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wide">Interno / Linkwave</span>
|
||||
</div>
|
||||
<div class="p-8">
|
||||
<div class="mb-6">
|
||||
<div class="w-12 h-12 bg-blue-900/20 rounded-lg flex items-center justify-center text-blue-400 mb-4 border border-blue-900/30">
|
||||
<i class="fa-solid fa-building-shield text-xl"></i>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold mb-1 text-white">Linkwave Internal CA</h2>
|
||||
<p class="text-sm text-gray-500">Para acessar sites e portais da Linkwave.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 mb-8 text-sm border-t border-gray-800 pt-6">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-500 text-xs uppercase">Algoritmo</span>
|
||||
<span class="text-gray-300">RSA 4096 / SHA-384</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-500 text-xs uppercase">Validade</span>
|
||||
<span class="text-gray-300">31 Dez 2045</span>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<p class="text-gray-500 text-xs uppercase">Fingerprint (SHA-256)</p>
|
||||
<div class="flex items-center bg-[#0a0a0a] rounded p-2 border border-gray-800 group-hover:border-gray-700 transition-colors overflow-hidden">
|
||||
<code class="text-xs text-gray-400 break-all flex-grow font-mono">AA:11:BB:22:CC:33:DD:44:EE:55:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00</code>
|
||||
<button onclick="copyFingerprint('internal')" class="ml-2 text-gray-500 hover:text-white transition-colors flex-shrink-0" title="Copiar">
|
||||
<i class="fa-regular fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<button onclick="downloadCertificate('internal_root', 'crt')" class="w-full bg-blue-600 hover:bg-blue-500 text-white px-6 py-3 rounded-xl font-semibold transition-all flex items-center justify-center gap-2 shadow-lg hover:shadow-blue-900/20">
|
||||
<i class="fa-solid fa-download"></i>
|
||||
Baixar Root Interno (.crt)
|
||||
</button>
|
||||
<div class="checksum-box" title="SHA-256 Hash do arquivo .crt" onclick="copyText(this.innerText)">
|
||||
<i class="fa-solid fa-hashtag text-[10px] shrink-0"></i> <span>SHA256: 7f83b165...e9a2 (Clique p/ copiar)</span>
|
||||
</div>
|
||||
<button onclick="downloadCertificate('internal_root', 'pem')" class="w-full bg-transparent hover:bg-gray-900 text-gray-300 border border-gray-700 px-6 py-3 rounded-xl font-medium transition-all text-sm mt-2">
|
||||
Baixar formato PEM
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CARD 2: EXTERNAL ROOT -->
|
||||
<div class="bg-[#111111] rounded-2xl shadow-2xl border border-gray-800 overflow-hidden relative group hover:border-purple-900/50 transition-all">
|
||||
<div class="absolute top-0 right-0 p-4">
|
||||
<span class="bg-purple-900/20 border border-purple-900/50 text-purple-400 text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wide">Externo / Geral</span>
|
||||
</div>
|
||||
<div class="p-8">
|
||||
<div class="mb-6">
|
||||
<div class="w-12 h-12 bg-purple-900/20 rounded-lg flex items-center justify-center text-purple-400 mb-4 border border-purple-900/30">
|
||||
<i class="fa-solid fa-globe text-xl"></i>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold mb-1 text-white">Linkwave External CA</h2>
|
||||
<p class="text-sm text-gray-500">Para clientes em geral e serviços hospedados.</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 mb-8 text-sm border-t border-gray-800 pt-6">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-500 text-xs uppercase">Algoritmo</span>
|
||||
<span class="text-gray-300">RSA 2048 / SHA-256</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-500 text-xs uppercase">Validade</span>
|
||||
<span class="text-gray-300">31 Dez 2035</span>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<p class="text-gray-500 text-xs uppercase">Fingerprint (SHA-256)</p>
|
||||
<div class="flex items-center bg-[#0a0a0a] rounded p-2 border border-gray-800 group-hover:border-gray-700 transition-colors overflow-hidden">
|
||||
<code class="text-xs text-gray-400 break-all flex-grow font-mono">99:88:77:66:55:44:33:22:11:00:FF:EE:DD:CC:BB:AA:99:88:77:66:55:44:33:22:11:00:FF:EE:DD</code>
|
||||
<button onclick="copyFingerprint('external')" class="ml-2 text-gray-500 hover:text-white transition-colors flex-shrink-0" title="Copiar">
|
||||
<i class="fa-regular fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<button onclick="downloadCertificate('external_root', 'crt')" class="w-full bg-white hover:bg-gray-200 text-black px-6 py-3 rounded-xl font-semibold transition-all flex items-center justify-center gap-2 shadow-lg">
|
||||
<i class="fa-solid fa-download"></i>
|
||||
Baixar Root Global (.crt)
|
||||
</button>
|
||||
<div class="checksum-box" title="SHA-256 Hash do arquivo .crt" onclick="copyText(this.innerText)">
|
||||
<i class="fa-solid fa-hashtag text-[10px] shrink-0"></i> <span>SHA256: a1b2c3d4...f6e5 (Clique p/ copiar)</span>
|
||||
</div>
|
||||
<button onclick="downloadCertificate('external_root', 'pem')" class="w-full bg-transparent hover:bg-gray-900 text-gray-300 border border-gray-700 px-6 py-3 rounded-xl font-medium transition-all text-sm mt-2">
|
||||
Baixar formato PEM
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- TECHNICAL DOWNLOADS AREA -->
|
||||
<div class="max-w-5xl mx-auto mb-20 bg-[#0a0a0a] border border-gray-800 rounded-xl overflow-hidden">
|
||||
<div class="px-6 py-4 bg-[#111111] border-b border-gray-800 flex justify-between items-center">
|
||||
<h3 class="text-sm font-bold text-gray-300 uppercase tracking-wider flex items-center gap-2">
|
||||
<i class="fa-solid fa-server text-gray-500"></i> Área Técnica / SysAdmin
|
||||
</h3>
|
||||
<span class="text-[10px] md:text-xs text-gray-500">Para configuração de servidores</span>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 divide-y md:divide-y-0 md:divide-x divide-gray-800">
|
||||
<!-- Internal Tech Downloads -->
|
||||
<div class="p-6">
|
||||
<h4 class="text-white font-semibold mb-1 text-sm">Cadeia Interna</h4>
|
||||
<p class="text-xs text-gray-500 mb-4">Intermediária Única (ICA) para todo uso interno.</p>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<button onclick="downloadCertificate('internal_inter', 'crt')" class="w-full flex items-center justify-between px-4 py-3 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-file-contract mr-2 text-blue-500"></i>Intermediária (.crt)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<div class="checksum-box" onclick="copyText(this.innerText)">SHA256: 1234abcd...5678</div>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="downloadCertificate('internal_bundle', 'pem')" class="w-full flex items-center justify-between px-4 py-3 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-box-archive mr-2 text-blue-500"></i>Bundle (Root + ICA)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<div class="checksum-box" onclick="copyText(this.innerText)">SHA256: 9876fedc...1029</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- External Tech Downloads -->
|
||||
<div class="p-6">
|
||||
<h4 class="text-white font-semibold mb-1 text-sm">Cadeia Externa</h4>
|
||||
<p class="text-xs text-gray-500 mb-4">Segregada em Web (Sites) e Infraestrutura.</p>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Web Chain -->
|
||||
<div>
|
||||
<span class="text-[10px] uppercase text-gray-500 font-bold tracking-wider mb-2 block">01. Sites / Web SSL</span>
|
||||
<div class="space-y-2">
|
||||
<button onclick="downloadCertificate('external_web', 'crt')" class="w-full flex items-center justify-between px-4 py-2 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-globe mr-2 text-purple-500"></i>ICA Web (.crt)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<button onclick="downloadCertificate('external_web_bundle', 'pem')" class="w-full flex items-center justify-between px-4 py-2 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-box-archive mr-2 text-purple-500"></i>Bundle (Root+Int)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<div class="checksum-box" onclick="copyText(this.innerText)">SHA256: web12345...6789</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Infra Chain -->
|
||||
<div>
|
||||
<span class="text-[10px] uppercase text-gray-500 font-bold tracking-wider mb-2 block">02. Servidores / Emails</span>
|
||||
<div class="space-y-2">
|
||||
<button onclick="downloadCertificate('external_infra', 'crt')" class="w-full flex items-center justify-between px-4 py-2 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-server mr-2 text-purple-500"></i>ICA Infra (.crt)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<button onclick="downloadCertificate('external_infra_bundle', 'pem')" class="w-full flex items-center justify-between px-4 py-2 bg-gray-900 hover:bg-gray-800 border border-gray-800 rounded text-xs text-gray-300 transition-colors group">
|
||||
<span class="group-hover:text-white transition-colors truncate"><i class="fa-solid fa-box-archive mr-2 text-purple-500"></i>Bundle (Root+Int)</span>
|
||||
<i class="fa-solid fa-download text-gray-600 group-hover:text-white shrink-0 ml-2"></i>
|
||||
</button>
|
||||
<div class="checksum-box" onclick="copyText(this.innerText)">SHA256: inf54321...9876</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Installation Instructions -->
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h2 class="text-2xl font-bold mb-8 text-center text-white">Instruções de Instalação (Cliente)</h2>
|
||||
<p class="text-center text-gray-500 mb-8 text-sm">Para usuários finais, basta instalar o Certificado Root (acima).</p>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="border border-gray-800 rounded-xl overflow-hidden bg-[#111111]">
|
||||
<button class="w-full px-6 py-4 text-left flex justify-between items-center hover:bg-gray-900 transition-colors" onclick="toggleAccordion('windows')">
|
||||
<span class="font-medium flex items-center gap-3 text-gray-200"><i class="fa-brands fa-windows text-lg text-blue-500"></i> Windows</span>
|
||||
<i id="icon-windows" class="fa-solid fa-chevron-down text-gray-600 text-sm transition-transform"></i>
|
||||
</button>
|
||||
<div id="content-windows" class="hidden px-6 py-4 bg-[#0a0a0a] text-sm text-gray-400 space-y-2 border-t border-gray-800">
|
||||
<p>1. Baixe o arquivo <strong>.crt</strong> desejado (Interno ou Global).</p>
|
||||
<p>2. Clique duas vezes no arquivo e selecione "Instalar Certificado".</p>
|
||||
<p>3. Selecione "Máquina Local" (Requer Admin) para aplicar a todo o sistema.</p>
|
||||
<p>4. Escolha "Colocar todos os certificados no repositório a seguir".</p>
|
||||
<p>5. Selecione <strong>"Autoridades de Certificação Raiz Confiáveis"</strong> e conclua.</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Outros sistemas... -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PAGE: TOOLS (NEW) -->
|
||||
<div id="page-tools" class="page-section hidden">
|
||||
<div class="max-w-5xl mx-auto pt-8">
|
||||
<div class="text-center mb-12">
|
||||
<h1 class="text-3xl font-bold text-white mb-4">Ferramentas de Diagnóstico PKI</h1>
|
||||
<p class="text-gray-500">Utilitários para administradores e auditores de segurança.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<!-- TOOL 1: DECODER -->
|
||||
<div class="bg-[#111111] border border-gray-800 rounded-xl p-6">
|
||||
<div class="flex items-center gap-3 mb-4 border-b border-gray-800 pb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-blue-900/20 flex items-center justify-center text-blue-400 shrink-0">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-bold text-white">Decodificador CSR / Certificado</h3>
|
||||
<p class="text-xs text-gray-500">Analise o conteúdo de arquivos .csr ou .crt (PEM).</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<textarea id="decoder-input" rows="6" class="w-full bg-[#0a0a0a] border border-gray-700 rounded-lg p-3 text-xs font-mono text-gray-300 focus:outline-none focus:border-blue-500" placeholder="-----BEGIN CERTIFICATE REQUEST-----..."></textarea>
|
||||
<button onclick="decodePEM()" class="w-full bg-blue-600 hover:bg-blue-500 text-white py-3 md:py-2 rounded-lg font-medium text-sm transition-colors">
|
||||
Decodificar Conteúdo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Decoder Output -->
|
||||
<div id="decoder-output" class="hidden mt-6 space-y-2 border-t border-gray-800 pt-4 overflow-hidden">
|
||||
<!-- Filled by JS -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TOOL 2: SSL VERIFIER -->
|
||||
<div class="bg-[#111111] border border-gray-800 rounded-xl p-6">
|
||||
<div class="flex items-center gap-3 mb-4 border-b border-gray-800 pb-4">
|
||||
<div class="w-10 h-10 rounded-full bg-green-900/20 flex items-center justify-center text-green-400 shrink-0">
|
||||
<i class="fa-solid fa-shield-halved"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-bold text-white">Verificador de Confiança SSL</h3>
|
||||
<p class="text-xs text-gray-500">Teste se o navegador confia na URL (Interna/Externa).</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="flex flex-col sm:flex-row gap-2">
|
||||
<input id="ssl-url-input" type="text" placeholder="https://portal.linkwave.local" class="flex-grow bg-[#0a0a0a] border border-gray-700 rounded-lg px-3 py-3 md:py-2 text-sm text-white focus:outline-none focus:border-green-500">
|
||||
<button onclick="checkSSL()" class="bg-green-700 hover:bg-green-600 text-white px-6 py-3 md:py-2 rounded-lg font-medium text-sm transition-colors">
|
||||
Testar
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-[10px] text-gray-500 italic">Nota: Verifica apenas se a cadeia está confiável neste dispositivo. Detalhes profundos requerem acesso backend.</p>
|
||||
</div>
|
||||
|
||||
<!-- SSL Output -->
|
||||
<div id="ssl-output" class="hidden mt-6">
|
||||
<!-- Filled by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PAGE: POLICIES (CPS) -->
|
||||
<div id="page-policies" class="page-section hidden">
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<div class="mb-10 border-b border-gray-800 pb-8 pt-8 md:pt-0">
|
||||
<h1 class="text-2xl md:text-3xl font-bold text-white mb-2">Declaração de Práticas de Certificação</h1>
|
||||
<p class="text-gray-500 text-sm md:text-base">Linkwave Connect Private PKI · Versão 1.2 · Atualizado em 2024</p>
|
||||
</div>
|
||||
<div class="space-y-12 text-gray-300 leading-relaxed text-sm md:text-base">
|
||||
<section>
|
||||
<h2 class="text-lg md:text-xl font-semibold text-white mb-4 flex items-center gap-2">
|
||||
<span class="text-blue-500">1.</span> Estrutura Hierárquica
|
||||
</h2>
|
||||
<p class="mb-4">A Linkwave Connect opera duas cadeias de confiança distintas para garantir a segregação de deveres e segurança.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PAGE: CRL (REVOCATION) -->
|
||||
<div id="page-crl" class="page-section hidden">
|
||||
<div class="max-w-4xl mx-auto pt-8 md:pt-0">
|
||||
<div class="text-center mb-12">
|
||||
<h1 class="text-2xl md:text-3xl font-bold text-white mb-4">Lista de Certificados Revogados (CRL)</h1>
|
||||
<p class="text-gray-500 text-sm md:text-base">Verifique a validade de certificados emitidos por qualquer uma de nossas Roots.</p>
|
||||
</div>
|
||||
|
||||
<!-- Search Box -->
|
||||
<div class="bg-[#111111] border border-gray-800 rounded-xl p-6 md:p-8 mb-12">
|
||||
<label class="block text-sm font-medium text-gray-400 mb-2">Verificar Status por Número de Série</label>
|
||||
<div class="flex flex-col sm:flex-row gap-4">
|
||||
<input id="serial-input" type="text" placeholder="Ex: 01:23:45:67:89" class="w-full flex-grow bg-[#0a0a0a] border border-gray-700 rounded-lg px-4 py-3 text-white focus:outline-none focus:border-blue-500 font-mono uppercase">
|
||||
<button onclick="checkRevocation()" class="w-full sm:w-auto bg-gray-800 hover:bg-gray-700 text-white px-6 py-3 rounded-lg font-medium transition-colors shadow-sm">
|
||||
Verificar
|
||||
</button>
|
||||
</div>
|
||||
<p id="search-error" class="hidden text-red-500 text-xs mt-2 ml-1"><i class="fa-solid fa-triangle-exclamation mr-1"></i> Erro ao conectar com a base de dados.</p>
|
||||
|
||||
<div id="result-display" class="hidden mt-6"></div>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-6">
|
||||
<div class="bg-[#111111] p-6 rounded-xl border border-gray-800 text-center">
|
||||
<h4 class="text-white font-bold mb-2">CRL - Interna</h4>
|
||||
<p class="text-xs text-gray-500 mb-4">Atualizado: Hoje às 08:00</p>
|
||||
<button onclick="downloadCRL('internal')" class="text-blue-400 hover:text-white text-sm hover:underline py-2 md:py-0"><i class="fa-solid fa-download mr-1"></i> Baixar lista (.crl)</button>
|
||||
<div class="checksum-box justify-center mt-4 md:mt-2" onclick="copyText(this.innerText)">SHA256: crl1int...hash</div>
|
||||
</div>
|
||||
<div class="bg-[#111111] p-6 rounded-xl border border-gray-800 text-center">
|
||||
<h4 class="text-white font-bold mb-2">CRL - Global</h4>
|
||||
<p class="text-xs text-gray-500 mb-4">Atualizado: Hoje às 09:30</p>
|
||||
<button onclick="downloadCRL('external')" class="text-purple-400 hover:text-white text-sm hover:underline py-2 md:py-0"><i class="fa-solid fa-download mr-1"></i> Baixar lista (.crl)</button>
|
||||
<div class="checksum-box justify-center mt-4 md:mt-2" onclick="copyText(this.innerText)">SHA256: crl2ext...hash</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- Footer with Service Health -->
|
||||
<footer class="border-t border-gray-900 bg-[#050505] pt-10 pb-6 mt-auto relative z-20">
|
||||
<div class="max-w-6xl mx-auto px-4">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center mb-8 gap-8">
|
||||
<div class="text-center md:text-left">
|
||||
<h4 class="text-white font-semibold mb-2">Linkwave Connect LTDA</h4>
|
||||
<p class="text-xs text-gray-600 font-mono">CNPJ: 53.108.042/0001-07</p>
|
||||
</div>
|
||||
|
||||
<!-- SERVICE HEALTH WIDGET -->
|
||||
<div class="bg-[#111111] border border-gray-800 rounded-lg p-4 flex gap-4 md:gap-6 text-xs w-full md:w-auto justify-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
|
||||
<span class="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
|
||||
</span>
|
||||
<span class="text-gray-400">Emissão</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2 h-2 rounded-full bg-green-500"></span>
|
||||
<span class="text-gray-400">CRL Dist.</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2 h-2 rounded-full bg-green-500"></span>
|
||||
<span class="text-gray-400">OCSP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-xs text-gray-700 border-t border-gray-900 pt-6">
|
||||
© <span id="copyright-year">2024</span> Linkwave Connect LTDA. Todos os direitos reservados.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div id="toast-container" class="fixed bottom-5 right-5 z-50 flex flex-col gap-2"></div>
|
||||
|
||||
<script>
|
||||
// ROUTER LOGIC
|
||||
function navigateTo(pageId) {
|
||||
document.querySelectorAll('.page-section').forEach(el => el.classList.add('hidden'));
|
||||
document.getElementById(`page-${pageId}`).classList.remove('hidden');
|
||||
document.querySelectorAll('.nav-link').forEach(el => {
|
||||
el.classList.remove('active', 'text-white', 'border-blue-500');
|
||||
el.classList.add('border-transparent');
|
||||
});
|
||||
const activeNav = document.getElementById(`nav-${pageId}`);
|
||||
if(activeNav) {
|
||||
activeNav.classList.add('active');
|
||||
activeNav.classList.remove('border-transparent');
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
function toggleMobile() {
|
||||
document.getElementById('mobile-menu').classList.toggle('hidden');
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
navigateTo('home');
|
||||
|
||||
// Lógica do Ano Dinâmico no Footer
|
||||
const startYear = 2023, currentYear = new Date().getFullYear();
|
||||
const yearEl = document.getElementById('copyright-year');
|
||||
if(yearEl) yearEl.textContent = currentYear > startYear ? `${startYear}-${currentYear}` : startYear;
|
||||
|
||||
// Carrega a base de certificados externamente e sempre a versão mais atual (evitando cache)
|
||||
const script = document.createElement('script');
|
||||
script.src = `certificates.js?t=${new Date().getTime()}`;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// TOOL 1: DECODER LOGIC
|
||||
// ==========================================
|
||||
function decodePEM() {
|
||||
const pem = document.getElementById('decoder-input').value.trim();
|
||||
const output = document.getElementById('decoder-output');
|
||||
output.innerHTML = '';
|
||||
output.classList.remove('hidden');
|
||||
|
||||
if (!pem.startsWith('-----BEGIN')) {
|
||||
output.innerHTML = '<p class="text-red-500 text-xs">Erro: Formato inválido. Cole um PEM completo.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let subject = "Desconhecido", issuer = "N/A", serial = "N/A", notBefore = "N/A", notAfter = "N/A", type = "Desconhecido";
|
||||
|
||||
if (pem.includes("CERTIFICATE REQUEST")) {
|
||||
type = "CSR (Requisição)";
|
||||
const csr = new KJUR.asn1.csr.CertificationRequest({pem: pem});
|
||||
subject = csr.getSubjectString();
|
||||
// CSR não tem issuer/dates
|
||||
} else {
|
||||
type = "Certificado (CRT)";
|
||||
const x = new X509();
|
||||
x.readCertPEM(pem);
|
||||
|
||||
subject = x.getSubjectString();
|
||||
issuer = x.getIssuerString();
|
||||
serial = x.getSerialNumberHex();
|
||||
notBefore = x.getNotBefore();
|
||||
notAfter = x.getNotAfter();
|
||||
}
|
||||
const formatX500 = (str) => str.replace(/\//g, '<br/><span class="text-gray-500">/</span> ').substring(1);
|
||||
output.innerHTML = `
|
||||
<div class="grid grid-cols-1 gap-2 text-xs font-mono text-gray-300">
|
||||
<div class="bg-gray-900 p-2 rounded border border-gray-800"><span class="text-blue-400 block mb-1">TIPO</span>${type}</div>
|
||||
<div class="bg-gray-900 p-2 rounded border border-gray-800 break-words"><span class="text-blue-400 block mb-1">SUJEITO (SUBJECT)</span>${formatX500(subject)}</div>
|
||||
${issuer !== "N/A" ? `<div class="bg-gray-900 p-2 rounded border border-gray-800 break-words"><span class="text-blue-400 block mb-1">EMISSOR (ISSUER)</span>${formatX500(issuer)}</div>` : ''}
|
||||
${serial !== "N/A" ? `<div class="bg-gray-900 p-2 rounded border border-gray-800 break-all"><span class="text-blue-400 block mb-1">SERIAL</span>${serial}</div>` : ''}
|
||||
${notBefore !== "N/A" ? `<div class="bg-gray-900 p-2 rounded border border-gray-800"><span class="text-blue-400 block mb-1">VALIDADE</span>De: ${notBefore}<br/>Até: ${notAfter}</div>` : ''}
|
||||
</div>`;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
output.innerHTML = `<p class="text-red-500 text-xs">Erro ao decodificar: ${e.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// TOOL 2: SSL CHECKER LOGIC
|
||||
// ==========================================
|
||||
async function checkSSL() {
|
||||
let url = document.getElementById('ssl-url-input').value.trim();
|
||||
const output = document.getElementById('ssl-output');
|
||||
if(!url) return;
|
||||
if(!url.startsWith('http')) url = 'https://' + url;
|
||||
|
||||
output.classList.remove('hidden');
|
||||
output.innerHTML = '<div class="text-xs text-gray-500"><i class="fa-solid fa-spinner fa-spin"></i> Conectando...</div>';
|
||||
|
||||
try {
|
||||
await fetch(url, { method: 'HEAD', mode: 'no-cors' });
|
||||
output.innerHTML = `<div class="bg-green-900/20 border border-green-500/50 rounded-lg p-3"><div class="flex items-center gap-3"><i class="fa-solid fa-lock text-green-500 text-xl shrink-0"></i><div><h4 class="text-green-400 font-bold text-sm">Conexão Segura e Confiável</h4><p class="text-gray-400 text-xs">O navegador confia no certificado deste site.</p></div></div></div>`;
|
||||
} catch (e) {
|
||||
output.innerHTML = `<div class="bg-red-900/20 border border-red-500/50 rounded-lg p-3"><div class="flex items-center gap-3"><i class="fa-solid fa-triangle-exclamation text-red-500 text-xl shrink-0"></i><div><h4 class="text-red-400 font-bold text-sm">Falha de Confiança ou Conexão</h4><p class="text-gray-400 text-xs">O certificado não é confiável ou expirou.</p></div></div></div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// HELPERS
|
||||
// ==========================================
|
||||
function copyText(text) {
|
||||
const cleanText = text.replace('SHA256: ', '').replace(' (Clique p/ copiar)', '');
|
||||
navigator.clipboard.writeText(cleanText);
|
||||
showToast("Hash copiado!");
|
||||
}
|
||||
|
||||
function toggleAccordion(id) {
|
||||
const content = document.getElementById(`content-${id}`);
|
||||
const icon = document.getElementById(`icon-${id}`);
|
||||
content.classList.toggle('hidden');
|
||||
icon.style.transform = content.classList.contains('hidden') ? 'rotate(0deg)' : 'rotate(180deg)';
|
||||
}
|
||||
|
||||
function downloadFile(filename, content) {
|
||||
const element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
|
||||
element.setAttribute('download', filename);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
showToast("Download iniciado: " + filename);
|
||||
}
|
||||
|
||||
function downloadCertificate(type, format) {
|
||||
if (typeof pkiData === 'undefined' || !pkiData.certificates[type]) {
|
||||
showToast("Erro: Arquivo não configurado na base de certificados.");
|
||||
return;
|
||||
}
|
||||
let content = pkiData.certificates[type].trim();
|
||||
downloadFile(`linkwave-${type}.${format}`, content);
|
||||
}
|
||||
|
||||
function downloadCRL(type) {
|
||||
if (typeof pkiData === 'undefined' || !pkiData.crls[type]) {
|
||||
showToast("Erro: Lista não configurada na base de certificados.");
|
||||
return;
|
||||
}
|
||||
let content = pkiData.crls[type].trim();
|
||||
downloadFile(`linkwave-${type}.crl`, content);
|
||||
}
|
||||
|
||||
async function checkRevocation() {
|
||||
const input = document.getElementById('serial-input').value;
|
||||
const display = document.getElementById('result-display');
|
||||
const errorMsg = document.getElementById('search-error');
|
||||
display.classList.add('hidden');
|
||||
errorMsg.classList.add('hidden');
|
||||
|
||||
const cleanSerial = input.replace(/[^a-fA-F0-9]/g, '').toUpperCase();
|
||||
if (cleanSerial.length === 0) { showToast("Digite um serial."); return; }
|
||||
|
||||
display.classList.remove('hidden');
|
||||
display.innerHTML = '<div class="text-center text-gray-500 py-4 text-xs">Verificando...</div>';
|
||||
|
||||
try {
|
||||
const uniqueUrl = `revocations.json?t=${new Date().getTime()}`;
|
||||
const response = await fetch(uniqueUrl, { cache: 'no-store' });
|
||||
if (!response.ok) throw new Error("404");
|
||||
const db = await response.json();
|
||||
|
||||
const result = db[cleanSerial];
|
||||
if (result) {
|
||||
display.innerHTML = `<div class="result-box bg-red-900/20 border border-red-500/50 rounded-lg p-4"><h3 class="text-red-400 font-bold text-sm mb-1"><i class="fa-solid fa-circle-xmark mr-2"></i>REVOGADO</h3><div class="text-xs text-gray-400 grid grid-cols-1 sm:grid-cols-2 gap-2 mt-2"><div><span class="block text-gray-600">DATA</span>${result.data}</div><div><span class="block text-gray-600">MOTIVO</span>${result.motivo}</div></div></div>`;
|
||||
} else {
|
||||
display.innerHTML = `<div class="result-box bg-green-900/20 border border-green-500/50 rounded-lg p-4"><h3 class="text-green-400 font-bold text-sm"><i class="fa-solid fa-circle-check mr-2"></i>VÁLIDO / NÃO LISTADO</h3><p class="text-xs text-gray-500 mt-1 break-all">Serial: ${cleanSerial}</p></div>`;
|
||||
}
|
||||
} catch (error) {
|
||||
errorMsg.classList.remove('hidden');
|
||||
display.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function copyFingerprint(type) { showToast("Fingerprint copiado!"); }
|
||||
|
||||
function showToast(message) {
|
||||
const container = document.getElementById('toast-container');
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'toast bg-white text-black text-sm py-3 px-6 rounded-lg shadow-lg flex items-center gap-3 border border-gray-200';
|
||||
toast.innerHTML = `<i class="fa-solid fa-circle-check text-green-600"></i> ${message}`;
|
||||
container.appendChild(toast);
|
||||
setTimeout(() => {
|
||||
toast.classList.add('hiding');
|
||||
toast.addEventListener('animationend', () => toast.remove());
|
||||
}, 3000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
14
revocations.json
Normal file
14
revocations.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"0123456789ABCDEF": {
|
||||
"data": "2024-03-25 14:30:00",
|
||||
"motivo": "Chave Privada Comprometida"
|
||||
},
|
||||
"5F1A2B3C4D5E6F70": {
|
||||
"data": "2024-04-02 09:15:00",
|
||||
"motivo": "Certificado Substituído"
|
||||
},
|
||||
"AABBCCDDEEFF": {
|
||||
"data": "2024-04-05 16:45:00",
|
||||
"motivo": "Cessação de Operação"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue