mirror of
https://github.com/tlsnotary/proof_viz.git
synced 2026-01-08 22:48:21 -05:00
Allow setting the notary public key
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
pub mod redactedBytesComponent;
|
||||
pub mod viewFile;
|
||||
pub mod pem_input;
|
||||
pub mod redacted_bytes_component;
|
||||
pub mod view_file;
|
||||
|
||||
70
src/components/pem_input.rs
Normal file
70
src/components/pem_input.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use elliptic_curve::pkcs8::DecodePublicKey;
|
||||
// use gloo::console::log;
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::prelude::*;
|
||||
|
||||
#[derive(Properties, Clone, PartialEq)]
|
||||
pub struct Props {
|
||||
pub pem_callback: Callback<p256::PublicKey>,
|
||||
}
|
||||
|
||||
// from https://github.com/tlsnotary/notary-server/tree/main/src/fixture/notary/notary.key
|
||||
// converted with `openssl ec -in notary.key -pubout -outform PEM`
|
||||
pub const DEFAULT_PEM: &str = "-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBv36FI4ZFszJa0DQFJ3wWCXvVLFr
|
||||
cRzMG5kaTeHGoSzDu6cFqx3uEWYpFGo6C0EOUgf+mEgbktLrXocv5yHzKg==
|
||||
-----END PUBLIC KEY-----";
|
||||
|
||||
#[function_component(PemInputComponent)]
|
||||
pub fn pem_input_component(Props { pem_callback }: &Props) -> Html {
|
||||
let input_value = use_state(|| DEFAULT_PEM.to_string());
|
||||
let invalid_input = use_state(|| None);
|
||||
|
||||
let oninput = {
|
||||
let input_value = input_value.clone();
|
||||
let callback = pem_callback.clone();
|
||||
let invalid_input = invalid_input.clone();
|
||||
|
||||
Callback::from(move |e: InputEvent| {
|
||||
let input: HtmlInputElement = e.target_unchecked_into();
|
||||
let value = input.value().trim().to_string();
|
||||
|
||||
let result = p256::PublicKey::from_public_key_pem(value.as_str());
|
||||
match result {
|
||||
Ok(public_key) => {
|
||||
input_value.set(value.clone());
|
||||
invalid_input.set(None);
|
||||
callback.emit(public_key.clone());
|
||||
}
|
||||
Err(err) => {
|
||||
input_value.set(value.clone());
|
||||
invalid_input.set(Some(err.to_string()));
|
||||
// do not emit a false pem here
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let style = if invalid_input.is_none() {
|
||||
"text-sm text-white border-gray-600 focus:ring-blue-500 focus:border-blue-500"
|
||||
} else {
|
||||
"text-sm text-pink-600 border-pink-500 focus:border-pink-500 focus:ring-pink-500"
|
||||
};
|
||||
|
||||
html! {
|
||||
<div class={style}>
|
||||
<details class="p-4 w-5/6" open={false}>
|
||||
<summary><b>{"Change Notary Public Key:" }</b>{if invalid_input.as_ref().is_some() {" ❌"} else {""}}</summary>
|
||||
<textarea class="block p-2.5 w-full bg-gray-700"
|
||||
id="pem-input"
|
||||
rows="4"
|
||||
value={input_value.to_string()}
|
||||
oninput={oninput} >
|
||||
</textarea>
|
||||
if let Some(x) = invalid_input.as_ref() {
|
||||
<p>{x}</p>
|
||||
}
|
||||
</details>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
extern crate base64;
|
||||
use elliptic_curve::pkcs8::DecodePublicKey;
|
||||
use std::str;
|
||||
use web_time::Duration;
|
||||
|
||||
@@ -7,41 +6,30 @@ use yew::{function_component, html, Html, Properties};
|
||||
|
||||
use tlsn_core::proof::{SessionProof, TlsProof};
|
||||
|
||||
use crate::components::redactedBytesComponent::Direction;
|
||||
use crate::components::redactedBytesComponent::RedactedBytesComponent;
|
||||
use crate::components::redacted_bytes_component::Direction;
|
||||
use crate::components::redacted_bytes_component::RedactedBytesComponent;
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct Props {
|
||||
pub name: String,
|
||||
pub file_type: String,
|
||||
pub data: Vec<u8>,
|
||||
pub pem: p256::PublicKey,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn ViewFile(props: &Props) -> Html {
|
||||
fn notary_pubkey() -> p256::PublicKey {
|
||||
// from https://github.com/tlsnotary/notary-server/tree/main/src/fixture/notary/notary.key
|
||||
// converted with `openssl ec -in notary.key -pubout -outform PEM`
|
||||
|
||||
let pem = "-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBv36FI4ZFszJa0DQFJ3wWCXvVLFr
|
||||
cRzMG5kaTeHGoSzDu6cFqx3uEWYpFGo6C0EOUgf+mEgbktLrXocv5yHzKg==
|
||||
-----END PUBLIC KEY-----";
|
||||
|
||||
p256::PublicKey::from_public_key_pem(pem).unwrap()
|
||||
}
|
||||
|
||||
// Verify the session proof against the Notary's public key
|
||||
fn verify_proof(session: &SessionProof) -> Result<(), String> {
|
||||
fn verify_proof(session: &SessionProof, pem: p256::PublicKey) -> Result<(), String> {
|
||||
// This verifies the identity of the server using a default certificate verifier which trusts
|
||||
// the root certificates from the `webpki-roots` crate.
|
||||
|
||||
session
|
||||
.verify_with_default_cert_verifier(notary_pubkey())
|
||||
.verify_with_default_cert_verifier(pem)
|
||||
.map_err(|err| err.to_string())
|
||||
}
|
||||
|
||||
fn parse_tls_proof(json_str: &str) -> Html {
|
||||
fn parse_tls_proof(json_str: &str, pem: p256::PublicKey) -> Html {
|
||||
let tls_proof: Result<TlsProof, serde_json::Error> = serde_json::from_str(json_str);
|
||||
|
||||
// info!("Parsing");
|
||||
@@ -57,7 +45,7 @@ cRzMG5kaTeHGoSzDu6cFqx3uEWYpFGo6C0EOUgf+mEgbktLrXocv5yHzKg==
|
||||
substrings,
|
||||
} = tls_proof;
|
||||
|
||||
let proof_verification = verify_proof(&session);
|
||||
let proof_verification = verify_proof(&session, pem);
|
||||
|
||||
if proof_verification.is_err() {
|
||||
return html! {
|
||||
@@ -137,7 +125,7 @@ cRzMG5kaTeHGoSzDu6cFqx3uEWYpFGo6C0EOUgf+mEgbktLrXocv5yHzKg==
|
||||
<div class="flex-1 flex flex-col justify-center p-4">
|
||||
<div class="container mx-auto px-4">
|
||||
if props.file_type.contains("application/json") {
|
||||
{parse_tls_proof(json_str)}
|
||||
{parse_tls_proof(json_str, props.pem)}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
21
src/main.rs
21
src/main.rs
@@ -3,12 +3,18 @@ use gloo::file::callbacks::FileReader;
|
||||
use gloo::file::File;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use gloo::console::log;
|
||||
|
||||
use web_sys::{DragEvent, Event, FileList, HtmlInputElement};
|
||||
use yew::html::TargetCast;
|
||||
use yew::{html, Callback, Component, Context, Html, Properties};
|
||||
use yew::prelude::*;
|
||||
|
||||
mod components;
|
||||
use crate::components::viewFile::ViewFile;
|
||||
use crate::components::pem_input::PemInputComponent;
|
||||
use crate::components::pem_input::DEFAULT_PEM;
|
||||
use crate::components::view_file::ViewFile;
|
||||
use elliptic_curve::pkcs8::DecodePublicKey;
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
struct FileDetails {
|
||||
@@ -20,11 +26,13 @@ struct FileDetails {
|
||||
pub enum Msg {
|
||||
Loaded(String, String, Vec<u8>),
|
||||
Files(Vec<File>),
|
||||
Pem(p256::PublicKey),
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
readers: HashMap<String, FileReader>,
|
||||
files: Vec<FileDetails>,
|
||||
pem: p256::PublicKey,
|
||||
}
|
||||
|
||||
impl Component for App {
|
||||
@@ -35,6 +43,7 @@ impl Component for App {
|
||||
Self {
|
||||
readers: HashMap::default(),
|
||||
files: Vec::default(),
|
||||
pem: p256::PublicKey::from_public_key_pem(DEFAULT_PEM).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +58,10 @@ impl Component for App {
|
||||
self.readers.remove(&file_name);
|
||||
true
|
||||
}
|
||||
Msg::Pem(pem) => {
|
||||
self.pem = pem;
|
||||
true
|
||||
}
|
||||
Msg::Files(files) => {
|
||||
for file in files.into_iter() {
|
||||
let file_name = file.name();
|
||||
@@ -151,9 +164,11 @@ impl Component for App {
|
||||
})}
|
||||
/>
|
||||
|
||||
<PemInputComponent pem_callback={ctx.link().callback(|pem| Msg::Pem(pem))}/>
|
||||
|
||||
<div>
|
||||
{for self.files.iter().rev().map(|file| html! {
|
||||
<ViewFile name={file.name.clone()} file_type={file.file_type.clone()} data={file.data.clone()} />
|
||||
<ViewFile name={file.name.clone()} file_type={file.file_type.clone()} data={file.data.clone()} pem={self.pem} />
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user