Skip to content

Commit

Permalink
refactor: cleanup and styling
Browse files Browse the repository at this point in the history
  • Loading branch information
natesales committed Nov 26, 2024
1 parent 6e8e4e0 commit 176cf44
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 127 deletions.
175 changes: 48 additions & 127 deletions wasm/index.html
Original file line number Diff line number Diff line change
@@ -1,164 +1,85 @@
<!DOCTYPE html>
<html>
<html class="bg-gray-50">
<head>
<title>Tinfoil Verifier</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<body class="min-h-screen">
<script src="wasm_exec.js"></script>
<script>
function verify() {
let repo = document.getElementById("repo").value;
let digest = document.getElementById("digest").value;
let domain = document.getElementById("domain").value;
let log = document.getElementById("log");
log.innerText = "";
<script src="verifier.js"></script>

function addLog(message) {
let timestamp = new Date().toLocaleString();
log.innerText += `${timestamp} - ${message}\n`;
}
<div class="container mx-auto p-6">
<div class="bg-white rounded-lg shadow-sm p-8">
<h1 class="text-3xl font-bold text-gray-800 mb-4">Tinfoil Verifier</h1>

addLog(`Verifying ${domain} against EIF digest ${digest}`);
addLog("Loading WASM verifier");
const go = new Go();
WebAssembly.instantiateStreaming(fetch("tinfoil-verifier.wasm"), go.importObject).then((result) => {
go.run(result.instance);
addLog("WASM verifier loaded");

let bundleURL = "https://api.github.com/repos/" + repo + "/attestations/sha256:" + digest;
addLog("Fetching attestation bundle from " + bundleURL);
let sigstorePromise = fetch(bundleURL)
.catch(error => {
addLog("Failed to fetch attestation bundle from Sigstore: " + error);
addLog("Verification failed");
})
.then(response => {
if (response.status !== 200) {
addLog("Failed to fetch attestation bundle from Sigstore: " + response.status);
addLog("Verification failed");

} else {
return response.json();
}
})
.then(data => {
let bundle = data.attestations[0].bundle;
addLog("Verifying sigstore signature");
let sigstoreMeasurements = JSON.parse(verifySigstore(digest, JSON.stringify(bundle), repo));
addLog("Sigstore PCR0: " + sigstoreMeasurements.PCR0);
addLog("Sigstore PCR1: " + sigstoreMeasurements.PCR1);
addLog("Sigstore PCR2: " + sigstoreMeasurements.PCR2);
return sigstoreMeasurements;
});

let nitroAttestationURL = `https://${domain}/.well-known/nitro-attestation`;
addLog("Fetching nitro signed attestation from " + nitroAttestationURL);
let nitroPromise = fetch(nitroAttestationURL)
.catch(error => {
addLog("Failed to fetch nitro attestation: " + error);
addLog("Verification failed");
})
.then(response => {
if (response.status !== 201) {
addLog("Failed to fetch nitro attestation: " + response.status);
addLog("Verification failed");

} else {
return response.json();
}
})
.then(nitroAttestation => {
let nitroMeasurements = JSON.parse(verifyNitro(nitroAttestation));
addLog("Nitro PCR0: " + nitroMeasurements.PCR0);
addLog("Nitro PCR1: " + nitroMeasurements.PCR1);
addLog("Nitro PCR2: " + nitroMeasurements.PCR2);
return nitroMeasurements;
});

// Wait for both to finish and print both
Promise.all([sigstorePromise, nitroPromise]).then(([sigstoreMeasurements, nitroMeasurements]) => {
let failed = false;
for (let i = 0; i < 3; i++) {
let sigstorePCR = sigstoreMeasurements["PCR" + i];
let nitroPCR = nitroMeasurements["PCR" + i];

if (sigstorePCR !== nitroPCR) {
addLog(`PCR${i} mismatch`);
failed = true;
} else {
addLog(`PCR${i} match`);
}
}

if (failed) {
addLog("Verification failed");
} else {
addLog("Verification successful! ✅");
}
});
});
}

window.addEventListener("load", function () {
verify();
});
</script>
</body>

<div class="container mx-auto p-4">
<div>

<h1 class="text-2xl font-bold">Tinfoil Verifier</h1>

<p class="text-gray-600">
<p class="text-gray-600 text-md mb-8">
This page demonstrates how to verify the attestation of a Nitro Enclave using the Tinfoil
verifier. See our <a
class="text-blue-500"
href="https://github.com/tinfoilanalytics/verifier">verifier code on GitHub</a> for more information.
class="text-blue-600 hover:text-blue-800 underline transition-colors"
href="https://github.com/tinfoilanalytics/verifier"
target="_blank"
rel="noopener noreferrer">verifier code on GitHub</a> for more information.
</p>

<div
class="border border-gray-200 p-4 mt-4"
>
<div class="flex flex-row gap-4 w-full mb-5">
<div class="w-[50%]">
<p class="text-gray-600 mb-2">EIF image hash (sha256):</p>
<div class="bg-gray-50 rounded-lg border border-gray-200 p-6">
<div class="flex gap-6 mb-6">
<div class="w-[35%]">
<label for="digest" class="block text-sm font-medium text-gray-700 mb-2">EIF image hash (sha256):</label>
<input
id="digest"
class="border border-gray-200 p-2 w-full"
class="border border-gray-300 rounded-md p-2.5 w-full focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
type="text"
value="6d87ba0d92af58c1d740b8aa7d2c3521d8cff96a520502a8b748c3a744ae015f">
</div>
<div class="w-[35%]">
<label for="repo" class="block text-sm font-medium text-gray-700 mb-2">Repo:</label>
<input
id="repo"
class="border border-gray-300 rounded-md p-2.5 w-full focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
type="text"
value="tinfoilanalytics/nitro-private-inference-image">
</div>
<div class="w-[20%]">
<p class="text-gray-600 mb-2">URL:</p>
<label for="domain" class="block text-sm font-medium text-gray-700 mb-2">URL:</label>
<input
id="domain"
class="border border-gray-200 p-2 w-full"
class="border border-gray-300 rounded-md p-2.5 w-full focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
type="text"
value="inference.tinfoil.sh">
</div>
<div class="w-[30%]">
<p class="text-gray-600 mb-2">Repo:</p>
<input
id="repo"
class="border border-gray-200 p-2 w-full"
type="text"
value="tinfoilanalytics/nitro-private-inference-image">
<div class="w-[10%] flex items-end">
<button
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2.5 rounded-md transition-colors duration-200 font-medium w-full"
onclick="verify()">
Verify
</button>
</div>
</div>

<div class="flex flex-col gap-4 mb-6">
<div>
<div class="text-sm font-medium text-gray-600 mb-2">Bundle URL:</div>
<div class="bg-gray-100 p-3 rounded-md">
<a id="bundleLink" href="#" class="text-blue-600 hover:text-blue-800 break-all text-sm block" target="_blank" rel="noopener noreferrer"></a>
</div>
</div>
<div class="w-[5%] flex items-end">
<button class="bg-emerald-500 text-white px-4 py-2 w-full" onclick="verify()">Verify</button>
<div>
<div class="text-sm font-medium text-gray-600 mb-2">Attestation URL:</div>
<div class="bg-gray-100 p-3 rounded-md">
<a id="attestationLink" href="#" class="text-blue-600 hover:text-blue-800 break-all text-sm block" target="_blank" rel="noopener noreferrer"></a>
</div>
</div>
</div>

<div
id="log"
class="bg-white p-4 border border-gray-200"
class="bg-white rounded-md p-4 border border-gray-200 min-h-[200px] font-mono text-sm"
></div>
</div>
</div>
</div>

</body>
</html>
127 changes: 127 additions & 0 deletions wasm/verifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
function updateLinks() {
let repo = document.getElementById("repo").value;
let digest = document.getElementById("digest").value;
let domain = document.getElementById("domain").value;

let bundleURL = "https://api.github.com/repos/" + repo + "/attestations/sha256:" + digest;
let attestationURL = `https://${domain}/.well-known/nitro-attestation`;

let bundleLink = document.getElementById("bundleLink");
let attestationLink = document.getElementById("attestationLink");

bundleLink.href = bundleURL;
bundleLink.textContent = bundleURL;

attestationLink.href = attestationURL;
attestationLink.textContent = attestationURL;
}

function verify() {
let repo = document.getElementById("repo").value;
let digest = document.getElementById("digest").value;
let domain = document.getElementById("domain").value;
let log = document.getElementById("log");
log.innerText = "";

updateLinks();

function addLog(message) {
let timestamp = new Date().toLocaleString();
log.innerText += `${timestamp} - ${message}\n`;
}

let bundleURL = document.getElementById("bundleLink").href;
let attestationURL = document.getElementById("attestationLink").href;

addLog(`Verifying ${domain} against EIF digest ${digest}`);
addLog("Loading WASM verifier");

const go = new Go();
WebAssembly.instantiateStreaming(fetch("tinfoil-verifier.wasm"), go.importObject).then((result) => {
go.run(result.instance);
addLog("WASM verifier loaded");

addLog("Fetching sigstore attestation bundle from GitHub");
let sigstorePromise = fetch(bundleURL)
.catch(error => {
addLog("Failed to fetch attestation bundle from Sigstore: " + error);
addLog("Verification failed");
throw error;
})
.then(response => {
if (response.status !== 200) {
let error = `Failed to fetch attestation bundle from Sigstore: ${response.status}`;
addLog(error);
throw new Error(error);
}
return response.json();
})
.then(data => {
let bundle = data.attestations[0].bundle;
addLog("Verifying sigstore signature");
let sigstoreMeasurements = JSON.parse(verifySigstore(digest, JSON.stringify(bundle), repo));
addLog("Sigstore PCR0: " + sigstoreMeasurements.PCR0);
addLog("Sigstore PCR1: " + sigstoreMeasurements.PCR1);
addLog("Sigstore PCR2: " + sigstoreMeasurements.PCR2);
return sigstoreMeasurements;
});

addLog("Fetching nitro attestation");
let nitroPromise = fetch(attestationURL)
.catch(error => {
addLog("Failed to fetch nitro attestation: " + error);
addLog("Verification failed");
throw error;
})
.then(response => {
if (response.status !== 201) {
let error = `Failed to fetch nitro attestation: ${response.status}`;
addLog(error);
throw new Error(error);
}
return response.json();
})
.then(nitroAttestation => {
let nitroMeasurements = JSON.parse(verifyNitro(nitroAttestation));
addLog("Nitro PCR0: " + nitroMeasurements.PCR0);
addLog("Nitro PCR1: " + nitroMeasurements.PCR1);
addLog("Nitro PCR2: " + nitroMeasurements.PCR2);
return nitroMeasurements;
});

// Wait for both to finish and print both
Promise.all([sigstorePromise, nitroPromise])
.then(([sigstoreMeasurements, nitroMeasurements]) => {
let failed = false;
for (let i = 0; i < 3; i++) {
let sigstorePCR = sigstoreMeasurements["PCR" + i];
let nitroPCR = nitroMeasurements["PCR" + i];

if (sigstorePCR !== nitroPCR) {
addLog(`PCR${i} mismatch`);
failed = true;
} else {
addLog(`PCR${i} match`);
}
}

if (failed) {
addLog("Verification failed");
} else {
addLog("Verification successful! ✅");
}
})
.catch(error => {
addLog("Verification failed: " + error);
});
});
}

window.addEventListener("load", function () {
// Update links when any input changes
document.getElementById("repo").addEventListener("input", updateLinks);
document.getElementById("digest").addEventListener("input", updateLinks);
document.getElementById("domain").addEventListener("input", updateLinks);

verify();
});

0 comments on commit 176cf44

Please sign in to comment.