Skip to content

Commit

Permalink
Change font to Fira + validate signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
schlagtim committed Feb 18, 2024
1 parent d0041a4 commit fe5b026
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 49 deletions.
10 changes: 6 additions & 4 deletions src/lib/sd-jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
type VerifyOptions,
} from "@sd-jwt/core";
import type { DisclosureWithDigest } from "@sd-jwt/types";
import * as jose from "jose";
import { importJWK, jwtVerify, type JWK, compactVerify } from "jose";

export enum SignatureMode {
Verified,
Expand Down Expand Up @@ -77,15 +77,17 @@ export function decodeSdJwt(encodedJwt: string) {

export async function validateJwtSignature(
jwt: string,
publicKeyJwk: jose.JWK,
publicKeyJwk: JWK,
alg?: string,
): Promise<boolean> {
try {
const publicKey = await jose.importJWK(publicKeyJwk, alg);
await jose.jwtVerify(jwt, publicKey);
const publicKey = await importJWK(publicKeyJwk, alg);

await compactVerify(jwt, publicKey);

return true;
} catch (error) {
console.error(error);
console.warn("JWT signature could not be verified");

return false;
Expand Down
41 changes: 36 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,62 @@
import Disclosures from "./Disclosures.svelte";
import Editor from "./Editor.svelte";
import Signature from "./Signature.svelte";
import type { JWK } from "jose";
// This is not yet fetched and only works for the default example
const publicKeyExampleJwt: JWK = {
crv: "Ed25519",
x: "i_XovdNwR_XoBSkTrZLt9yVQ36KhYbnvbJt0UdrkQTY",
kty: "OKP",
};
let encodedJwt: string | undefined =
"eyJhbGciOiJFZERTQSIsInR5cCI6InNkLWp3dCJ9.eyJpYXQiOjE3MDc2NjcxNTM2MzQsImlzcyI6ImRpZDprZXk6c29tZS1yYW5kb20tZGlkLWtleSIsIm5iZiI6MTcwNzY2NzE1MzczNCwiY3JlZGVudGlhbCI6eyJfc2QiOlsiNjRkUkN0YllkVkVMYW90eDBRVlFMZEdqcm9RSG1OUEI0TmI4b1BzbnE3YyIsIjZBMHF6TDQtZ3hrSkFuQ1EtSzN6b2hMYXo2Qzh3TUhXei0tSW41eFdsZmMiLCI2UFgxYXRrNEtpdm5NRDlSZjBMcF9LV2JBRkJVT1RPQjN1NzFmZzRPZ2NrIiwiWE4tZzluLXphODViVnhPaWlQUXF2Vl9VVmtLdG04VXlWbFZJZElCU3ltNCIsIm5Xc29GQ2V1cnFLZzJDbmFEeUxKMXV5UUtNUmtPdFFNMV95dUtaTjR5VlEiLCJ2bnBZcU1qOTdVMUZPX3VzRHhacWZVcl84Z2ZvdkpfdDNpVmo1OWtfZGkwIl19LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyJFX2N2SWNYOGYzYnZFNXVNVzctNEp5ZnNNMkNycUFhLVBjOU15MmtNaGFNIiwidlcxdWJSTUotVFBlRzIzS0J1OElleXlNeXVJRG5QNDB3SzR0YmRjbDdxdyIsInl5aTItMVJLaVNiR2YyY3hyX2VkQkljbVNUdzJMSVQ4dWUwVm1RemNpeTgiXX0.zeCXWQgiWFJIFZBVC9GKKSilJ--6u8OIQ4AnDRopKN4KQtYS8Z98ORxWb3_bDOdmNEHDvMqtAkEvxqk08_USCQ~WyJpSFFLaDlFM3BxZUluLXFvelVMMU93IiwiY3JlZGVudGlhbFN1YmplY3QiLCJkaWQ6cGVlcjo0cmVjZWl2ZXItcGVlci1kaWQiXQ~WyJxYzlObkVjeVA4YmsxV2RKTE53c1BBIiwiZGF0ZU9mQmlydGgiLCIyMDAwMDEwMSJd~WyJvVXJsUnNfRzlncWlQN2o4TDhPekd3IiwibmFtZSIsIkpvaG4iXQ~WyJpeld6c3BQMzUxdm55dzN0eno0blNnIiwibGFzdE5hbWUiLCJEb2UiXQ~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFZERTQSJ9.eyJpYXQiOjE3MDc2NjcxNTM2MzMsImF1ZCI6ImRpZDpwZWVyOjQ6c29tZS12ZXJpZmllciIsIm5vbmNlIjoiaVloOXBoU3ZWWTFVcUpsX05pNklJUSIsIl9zZF9oYXNoIjoiRTYwNWJfbnJPallsdUlSbktfQThKNTNhemwwcG8wcThBbHBJczZrQm5JWSJ9.6ZAydMHRVByM02Z79zQSWuZU3ZfNIkmVrMXM2ZVR-nN92h_J9D5-2cB7gPZ3aDP3Z-BY1Wj2kp_cIakv5ji3Cw";
"eyJhbGciOiJFZERTQSIsInR5cCI6InNkLWp3dCJ9.eyJpYXQiOjE3MDgyNzc4Mjg2NjIsImlzcyI6ImRpZDprZXk6c29tZS1yYW5kb20tZGlkLWtleSIsIm5iZiI6MTcwODI3NzgyODc2MiwiY3JlZGVudGlhbCI6eyJfc2QiOlsiSzRrc0gybmU3SFdmRVR6SUZEQmNZZHI4b0Ffc3cwQXk0cXZ2dmJoRjlqRSIsIlJVaWRCLS0xZHBUUEdZS2JiVXRKblZEb3IxNi1WdURHdFE3T2tEa25oUXciLCJzZC1Gd2c1UmhDZ2tOWWt6UktPSVJYUnFqQlBEZU1sZ2V6VC0yNTlDR19ZIiwidXdNcUlneGZGZG55aHhyVzdZYXNSc1JVLXB1dFNhdktOU3RiNWV0ZUJYUSIsInhiaEVQQ053RGhUMGpST2loWmltVnRwVWduRkNtSlBUZzVSNlpabTRQLWsiLCJ5dTRZRmJJOWktZHcySFZPS3ZQU01aWkZPR0hJNUtaYUpNUXlmQmJ3cFNFIl19LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI2c0JMdkVmWV9wRURlUEdFc3dnSE1iZ3BDWjJYVHpFZDNfNzRBbXBydlpjIiwiSE5RRFhzanhkWTg1MzBja21TMWRIOEE1MU9TVC1CclpKcktSaWZXeHZmSSIsImhLZnNUdUFnc3JVYmhtQTJCeE81ZlBXdzlLTjFTU05DVkRCNE9XWEdvS1UiXX0.t3ywqNYgweJppEMPkzRc7nMwtiz0HLLJZ5sLtBovGks3zkGbuy2O_MtSowVZN-GQ8RbOoZugFO0LjFQr-oMvCw~WyJBMlpsVGp6S05FZ3dva3REZjZKUmFnIiwiY3JlZGVudGlhbFN1YmplY3QiLCJkaWQ6cGVlcjo0cmVjZWl2ZXItcGVlci1kaWQiXQ~WyI1N2YxMC1WMFh1N1NOSV9DNmVhX1J3IiwiZGF0ZU9mQmlydGgiLCIyMDAwMDEwMSJd~WyIyN1ZUMlowN1R3Z2pMRkNEQjhUYTFnIiwibmFtZSIsIkpvaG4iXQ~WyJyNmJhVmFuM0tVUjR3czRwUzRHTThnIiwibGFzdE5hbWUiLCJEb2UiXQ~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFZERTQSJ9.eyJpYXQiOjE3MDgyNzc4Mjg2NjEsImF1ZCI6ImRpZDpwZWVyOjQ6c29tZS12ZXJpZmllciIsIm5vbmNlIjoiZnYtMWtHMDhpSjNOUDRob3E2NVBsUSIsIl9zZF9oYXNoIjoiX1JVZWxtVTVaNDYxeHB4MFhfdHY1M0oyekRXV0NrZmthOW94dkRXVGFBayJ9.clNC-bgPOffqVP1N6cBaxqMUI0sj8K9UonXcD6vfcPI3rzZwmkbIMF_w7WcAGFJ6Xzi14pY7DHAYVrnwu-klCA";
let jwtHeader = "";
let jwtPayload = "";
let disclosures: DisclosureWithDigest[] | undefined;
let alg: string | undefined;
let jwtPayloadSelection: string;
let signatureVerified: SignatureMode;
let signatureKeyBindingVerified: SignatureMode;
let showKeyBindingSignatureVerified: boolean = false;
let showKeyBindingSignatureVerified: boolean = true;
$: sdJwt = encodedJwt ? decodeSdJwt(encodedJwt) : undefined;
$: jwtHeader = sdJwt ? formatJsonObject(sdJwt?.header) : "";
$: jwtPayload = sdJwt ? formatJsonObject(sdJwt?.payload) : "";
$: alg = sdJwt ? (sdJwt?.payload["_sd_alg"] as string) : undefined;
$: encodedJwt
? validateJwtSignature(encodedJwt, {})
$: encodedJwtWithoutDisclosuresAndHolderBinding = encodedJwt
? encodedJwt.split("~").at(0)
: undefined;
$: encodedJwtWithoutDisclosuresAndHolderBinding
? validateJwtSignature(
encodedJwtWithoutDisclosuresAndHolderBinding,
publicKeyExampleJwt,
sdJwt?.header.alg as string,
)
.then((result) => {
signatureVerified = result ? SignatureMode.Verified : SignatureMode.CouldNotVerify;
signatureVerified = result ? SignatureMode.Verified : SignatureMode.Invalid;
})
.catch(() => {
signatureVerified = SignatureMode.CouldNotVerify;
})
: undefined;
$: encodedJwtHolderBinding = encodedJwt ? encodedJwt.split("~").at(-1) : undefined;
$: encodedJwtHolderBinding
? validateJwtSignature(
encodedJwtHolderBinding,
publicKeyExampleJwt,
sdJwt?.keyBinding?.header?.alg as string,
)
.then((result) => {
showKeyBindingSignatureVerified = true;
signatureKeyBindingVerified = result ? SignatureMode.Verified : SignatureMode.Invalid;
})
.catch(() => {
showKeyBindingSignatureVerified = true;
signatureKeyBindingVerified = SignatureMode.CouldNotVerify;
})
: (showKeyBindingSignatureVerified = false);
$: getDisclosures(sdJwt, alg)
.then((result) => {
disclosures = result;
Expand Down
1 change: 1 addition & 0 deletions src/routes/Editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
formatOnPaste: true,
formatOnType: true,
wordWrap: "on",
fontFamily: "Fira Mono",
// theme: "vs-dark",
tabSize: 2,
automaticLayout: true,
Expand Down
55 changes: 17 additions & 38 deletions src/routes/Signature.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,9 @@
export let showKeyBindingSignature: boolean = false;
export let keyBindingSignature: SignatureMode = SignatureMode.CouldNotVerify;
const signatureIssue = "⚠️ Could not verify";
const signatureValid = "✅ Signature Verified";
const signatureInvalid = "❌ Invalid Signature";
let jwtSignatureMessage: string;
let keyBindingSignatureMessage: string;
/*
function setSignatures(keyBinding: boolean) {
keyBindingSignature = keyBinding;
if (keyBinding) {
flexSize = 1;
} else {
flexSize = flexSize / 2;
}
}
setSignatures(false);
*/
function setSignatureMessage(mode: SignatureMode) {
switch (mode) {
case SignatureMode.CouldNotVerify:
return signatureIssue;
case SignatureMode.Verified:
return signatureValid;
case SignatureMode.Invalid:
return signatureInvalid;
default:
return signatureInvalid;
}
}
$: jwtSignatureMessage = setSignatureMessage(jwtSignature);
$: keyBindingSignatureMessage = setSignatureMessage(keyBindingSignature);
const signatureIssue = "Could not verify";
const signatureValid = "Signature Verified";
const signatureInvalid = "Invalid Signature";
</script>

<div class="box" style="--flex-size: {flexSize}">
Expand All @@ -52,12 +19,24 @@
<div class="signatures">
<div class="row">
<h3>JWT Signature:</h3>
<h3 class="signatures-right">{jwtSignatureMessage}</h3>
{#if jwtSignature === SignatureMode.Verified}
<h3 class="signatures-right" style="color: green">{signatureValid}</h3>
{:else if jwtSignature === SignatureMode.Invalid}
<h3 class="signatures-right" style="color: red">{signatureInvalid}</h3>
{:else}
<h3 class="signatures-right" style="color: orange">{signatureIssue}</h3>
{/if}
</div>
{#if showKeyBindingSignature}
<div class="row">
<h3>Key Binding Signature:</h3>
<h3 class="signatures-right">{keyBindingSignatureMessage}</h3>
{#if keyBindingSignature === SignatureMode.Verified}
<h3 class="signatures-right" style="color: green">{signatureValid}</h3>
{:else if keyBindingSignature === SignatureMode.Invalid}
<h3 class="signatures-right" style="color: red">{signatureInvalid}</h3>
{:else}
<h3 class="signatures-right" style="color: orange">{signatureIssue}</h3>
{/if}
</div>
{/if}
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/styles.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@import "@fontsource/fira-mono";

:root {
--font-body: Arial, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
--font-body: "Fira Mono", monospace, Arial, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
--font-mono: "Fira Mono", monospace;
--color-bg-0: rgb(202, 216, 228);
--color-bg-1: hsl(209, 36%, 86%);
Expand Down

0 comments on commit fe5b026

Please sign in to comment.