import { Controller, useForm } from "react-hook-form"; import { faFileSignature, faInfoCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; import { decodeBase64 } from "@app/components/utilities/cryptography/crypto"; import { Badge, Button, FormControl, Modal, ModalClose, ModalContent, Select, SelectItem, Switch, TextArea, Tooltip } from "@app/components/v2"; import { SigningAlgorithm, TCmek, useCmekVerify } from "@app/hooks/api/cmeks"; import { isBase64 } from "@app/lib/fn/base64"; const formSchema = z.object({ data: z.string().min(1, { message: "Data cannot be empty" }), signature: z .string() .min(1, { message: "Signature cannot be empty" }) .superRefine((val, ctx) => { if (!isBase64(val)) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Signature must be base64-encoded" }); } }), signingAlgorithm: z.nativeEnum(SigningAlgorithm), isBase64Encoded: z.boolean() }); export type FormData = z.infer; type Props = { isOpen: boolean; onOpenChange: (isOpen: boolean) => void; cmek: TCmek; }; type FormProps = Pick; const VerifyForm = ({ cmek }: FormProps) => { const cmekVerify = useCmekVerify(); const { handleSubmit, register, watch, control, formState: { isSubmitting, errors } } = useForm({ resolver: zodResolver(formSchema), defaultValues: { signingAlgorithm: cmek?.encryptionAlgorithm?.startsWith("RSA") ? SigningAlgorithm.RSASSA_PSS_SHA_512 : SigningAlgorithm.ECDSA_SHA_256, isBase64Encoded: false } }); const handleVerifyData = async (formData: FormData) => { try { const result = await cmekVerify.mutateAsync({ ...formData, keyId: cmek.id }); if (result.signatureValid) { createNotification({ text: "Successfully verified signature", type: "success" }); } else { createNotification({ title: "Signature Verification Failed", text: "The signature is invalid. The signature was not created using the same signing algorithm and key as the one used to sign the data. The data and signature may have been tampered with.", type: "error" }); } } catch (err) { console.error(err); createNotification({ text: "Failed to sign data", type: "error" }); } }; const signature = watch("signature"); const data = watch("data"); const isBase64Encoded = watch("isBase64Encoded"); const signatureValid = cmekVerify.data?.signatureValid; const signingAlgorithm = cmekVerify.data?.signingAlgorithm; const allowedSigningAlgorithms = Object.values(SigningAlgorithm).filter((a) => cmek?.encryptionAlgorithm?.startsWith("RSA") ? a.toLowerCase().startsWith("rsa") : a.toLowerCase().startsWith("ecdsa") ); return (
{signatureValid !== undefined ? (
Signature Status: {signatureValid ? (

Valid

) : (

Invalid

)}
Signing Algorithm: {signingAlgorithm}
Signature:{" "}
{signature}
Data:{" "}
{isBase64Encoded ? decodeBase64(data).toString() : data}
) : ( <>