Skip to content

Commit d5ba450

Browse files
committed
website: remove query
1 parent a88f358 commit d5ba450

2 files changed

Lines changed: 4 additions & 174 deletions

File tree

website/src/components/keyring-app.tsx

Lines changed: 2 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
77
import * as z from "zod";
88
import { toast } from "sonner";
99
import {
10-
Copy, Loader2, ShieldCheck, AlertTriangle, Search, Key,
10+
Copy, Loader2, AlertTriangle, Key,
1111
Github, Globe, Download, Upload, FileKey
1212
} from "lucide-react";
1313

@@ -194,10 +194,9 @@ export function KeyringApp() {
194194
{mounted ? (
195195
<Tabs defaultValue="generate" className="w-full">
196196
<div className="border-b px-6 py-2 bg-slate-50/50 dark:bg-slate-900/50">
197-
<TabsList className="grid w-full grid-cols-4 bg-slate-200/50 dark:bg-slate-800/50">
197+
<TabsList className="grid w-full grid-cols-3 bg-slate-200/50 dark:bg-slate-800/50">
198198
<TabsTrigger value="generate">{t.tabs.generate}</TabsTrigger>
199199
<TabsTrigger value="submit">{t.tabs.submit}</TabsTrigger>
200-
<TabsTrigger value="query">{t.tabs.query}</TabsTrigger>
201200
<TabsTrigger value="revoke">{t.tabs.revoke}</TabsTrigger>
202201
</TabsList>
203202
</div>
@@ -209,9 +208,6 @@ export function KeyringApp() {
209208
<TabsContent value="submit" forceMount className="data-[state=inactive]:hidden">
210209
<SubmitForm t={t} initialPublicKey={generatedPublicKey} />
211210
</TabsContent>
212-
<TabsContent value="query" forceMount className="data-[state=inactive]:hidden">
213-
<QueryForm t={t} />
214-
</TabsContent>
215211
<TabsContent value="revoke" forceMount className="data-[state=inactive]:hidden">
216212
<RevokeForm t={t} />
217213
</TabsContent>
@@ -468,152 +464,6 @@ function SubmitForm({ t, initialPublicKey }: { t: typeof locales.en; initialPubl
468464
);
469465
}
470466

471-
interface QueryResult {
472-
cn: string;
473-
fingerprint: string;
474-
serialNumber: string;
475-
issuer: string;
476-
validFrom: string;
477-
validTo: string;
478-
isValid: boolean;
479-
}
480-
481-
function QueryForm({ t }: { t: typeof locales.en }) {
482-
const [fp, setFp] = useState("");
483-
const [result, setResult] = useState<QueryResult | null>(null);
484-
const [loading, setLoading] = useState(false);
485-
486-
const handleFileImport = async (e: React.ChangeEvent<HTMLInputElement>) => {
487-
const file = e.target.files?.[0];
488-
if (!file) return;
489-
490-
const result = await parseCertFile(file);
491-
if (result && result.fingerprint) {
492-
setFp(result.fingerprint);
493-
toast.success(t.common.import_success);
494-
} else {
495-
toast.error(t.common.import_error);
496-
}
497-
e.target.value = "";
498-
};
499-
500-
const handleQuery = async () => {
501-
if (!fp) return toast.error("Please enter fingerprint");
502-
setLoading(true);
503-
setResult(null);
504-
try {
505-
// Fetch certificate bundle from repository
506-
const res = await fetch("https://raw.githubusercontent.com/KernelSU-Modules-Repo/developers/main/keyring/developers/");
507-
if (!res.ok) throw new Error("Failed to fetch certificate list");
508-
509-
// For now, we'll provide a direct certificate lookup interface
510-
// The actual implementation would iterate through available certificates
511-
const cleanFp = fp.replace(/[:\s]/g, "").toUpperCase();
512-
513-
// Placeholder: In production, this would fetch and search actual certificates
514-
toast.error(t.query.not_found + " (Certificate directory not yet configured)");
515-
516-
} catch (e) {
517-
toast.error(e instanceof Error ? e.message : String(e));
518-
} finally {
519-
setLoading(false);
520-
}
521-
};
522-
523-
// Direct certificate verification from file
524-
const handleVerifyCert = async (e: React.ChangeEvent<HTMLInputElement>) => {
525-
const file = e.target.files?.[0];
526-
if (!file) return;
527-
528-
try {
529-
const text = await file.text();
530-
const cert = new x509.X509Certificate(text);
531-
532-
const cn = cert.subject.split(',').find(s => s.trim().startsWith('CN='))?.split('=')[1]?.trim() || 'Unknown';
533-
const issuerCN = cert.issuer.split(',').find(s => s.trim().startsWith('CN='))?.split('=')[1]?.trim() || 'Unknown';
534-
const now = new Date();
535-
536-
setResult({
537-
cn,
538-
fingerprint: await getCertificateFingerprint(cert),
539-
serialNumber: cert.serialNumber,
540-
issuer: issuerCN,
541-
validFrom: cert.notBefore.toLocaleDateString(),
542-
validTo: cert.notAfter.toLocaleDateString(),
543-
isValid: now >= cert.notBefore && now <= cert.notAfter
544-
});
545-
toast.success(t.query.found);
546-
} catch (e) {
547-
toast.error(e instanceof Error ? e.message : String(e));
548-
}
549-
e.target.value = "";
550-
};
551-
552-
return (
553-
<div className="space-y-6 animate-in fade-in slide-in-from-bottom-2">
554-
<div>
555-
<h2 className="text-lg font-semibold">{t.query.title}</h2>
556-
<p className="text-sm text-slate-500">{t.query.desc}</p>
557-
</div>
558-
559-
<div className="space-y-2">
560-
<div className="flex justify-between">
561-
<Label>{t.query.ph}</Label>
562-
<div className="flex items-center gap-2">
563-
<Label htmlFor="verify-cert" className="cursor-pointer text-xs flex items-center gap-1 text-indigo-600 hover:bg-indigo-50 px-2 py-1 rounded">
564-
<FileKey className="w-3 h-3" /> {t.common.import_file}
565-
</Label>
566-
<Input id="verify-cert" type="file" className="hidden" accept=".pem,.cert,.crt" onChange={handleVerifyCert} />
567-
</div>
568-
</div>
569-
<div className="flex gap-2">
570-
<Input value={fp} onChange={e => setFp(e.target.value)} placeholder="AA:BB:CC:DD..." className="font-mono" />
571-
<Button onClick={handleQuery} disabled={loading}>
572-
{loading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Search className="w-4 h-4" />}
573-
</Button>
574-
</div>
575-
</div>
576-
577-
{result && (
578-
<Card className="bg-slate-50 dark:bg-slate-900">
579-
<CardContent className="p-4 space-y-3 text-sm">
580-
<div className="flex justify-between py-1 border-b">
581-
<span className="text-slate-500">Common Name (CN)</span>
582-
<span className="font-medium">{result.cn}</span>
583-
</div>
584-
<div className="flex justify-between py-1 border-b">
585-
<span className="text-slate-500">Serial Number</span>
586-
<span className="font-mono text-xs">{result.serialNumber}</span>
587-
</div>
588-
<div className="flex justify-between py-1 border-b">
589-
<span className="text-slate-500">Issuer</span>
590-
<span className="font-medium">{result.issuer}</span>
591-
</div>
592-
<div className="flex justify-between py-1 border-b">
593-
<span className="text-slate-500">Valid From</span>
594-
<span>{result.validFrom}</span>
595-
</div>
596-
<div className="flex justify-between py-1 border-b">
597-
<span className="text-slate-500">Valid To</span>
598-
<span>{result.validTo}</span>
599-
</div>
600-
<div className="flex justify-between py-1 border-b">
601-
<span className="text-slate-500">Status</span>
602-
<span className={result.isValid ? "text-green-600 font-medium" : "text-red-600 font-medium"}>
603-
{result.isValid ? "Valid ✓" : "Expired ✗"}
604-
</span>
605-
</div>
606-
<div className="pt-2">
607-
<span className="text-slate-500 block mb-1">Fingerprint (SHA-256)</span>
608-
<code className="block bg-slate-200 dark:bg-slate-800 p-2 rounded text-xs break-all">{result.fingerprint}</code>
609-
</div>
610-
</CardContent>
611-
</Card>
612-
)}
613-
</div>
614-
);
615-
}
616-
617467
function RevokeForm({ t }: { t: typeof locales.en }) {
618468
const form = useForm<z.infer<typeof revokeSchema>>({ resolver: zodResolver(revokeSchema) });
619469

website/src/lib/locales.ts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export const locales = {
33
en: {
44
title: "KernelSU Keyring",
55
subtitle: "Developer Identity Management System (X.509 PKI)",
6-
tabs: { generate: "Generate", submit: "Submit", query: "Query", revoke: "Revoke" },
6+
tabs: { generate: "Generate", submit: "Submit", revoke: "Revoke" },
77
gen: {
88
title: "Generate Key Pair",
99
desc: "Create a private key and public key locally for certificate issuance.",
@@ -24,16 +24,6 @@ export const locales = {
2424
btn: "Create GitHub Issue",
2525
warn: "Security: Never submit your private key, only the public key.",
2626
},
27-
query: {
28-
title: "Query Certificate",
29-
desc: "Verify a certificate from the official keyring.",
30-
ph: "Certificate Fingerprint (SHA-256)",
31-
btn: "Search Certificate",
32-
found: "Certificate Found ✅",
33-
not_found: "Certificate not found in official keyring.",
34-
self: "Self-Signed",
35-
core: "CA Verified",
36-
},
3727
revoke: {
3828
title: "Revoke Certificate",
3929
desc: "Create a request to revoke a compromised or lost certificate.",
@@ -61,7 +51,7 @@ export const locales = {
6151
zh: {
6252
title: "KernelSU 密钥库",
6353
subtitle: "开发者身份认证管理系统 (X.509 PKI)",
64-
tabs: { generate: "生成", submit: "提交", query: "查询", revoke: "吊销" },
54+
tabs: { generate: "生成", submit: "提交", revoke: "吊销" },
6555
gen: {
6656
title: "生成密钥对",
6757
desc: "在本地生成私钥和公钥以申请证书签发。",
@@ -82,16 +72,6 @@ export const locales = {
8272
btn: "创建 GitHub Issue",
8373
warn: "安全提示:永远不要提交您的私钥,仅提交公钥。",
8474
},
85-
query: {
86-
title: "查询证书",
87-
desc: "验证官方密钥库中的证书。",
88-
ph: "证书指纹 (SHA-256)",
89-
btn: "查询证书",
90-
found: "已找到证书 ✅",
91-
not_found: "未在官方库中找到此证书。",
92-
self: "自签名",
93-
core: "CA 认证",
94-
},
9575
revoke: {
9676
title: "吊销证书",
9777
desc: "创建请求以吊销泄露或丢失的证书。",

0 commit comments

Comments
 (0)