Implementing alpha.7 (#30)

This commit is contained in:
Tanner
2024-10-10 04:50:53 -07:00
committed by GitHub
parent 890094554a
commit 24cbc6a3ca
22 changed files with 2176 additions and 501 deletions

View File

@@ -9,7 +9,7 @@ COPY . .
RUN curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh -s -- -y
RUN npm i
RUN npm i --prefix rs/verifier/
RUN npm i --prefix rs/0.1.0-alpha.6/
RUN npm i --prefix rs/0.1.0-alpha.7/
RUN npm run build
# Create image for the app by copying build artifacts from builder

292
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,7 @@
"isomorphic-fetch": "^3.0.0",
"multiformats": "^13.1.0",
"node-forge": "^1.3.1",
"node-loader": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.1.2",
@@ -54,7 +55,7 @@
"redux-thunk": "^2.4.2",
"stream": "^0.0.2",
"tailwindcss": "^3.3.3",
"tlsn-js": "0.1.0-alpha.6.2",
"tlsn-js": "0.1.0-alpha.7.1",
"tlsn-js-v5": "npm:tlsn-js@0.1.0-alpha.5.4"
},
"devDependencies": {
@@ -92,7 +93,6 @@
"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.0",
"image-webpack-loader": "^8.1.0",
"node-loader": "^2.0.0",
"nodemon": "^3.0.3",
"postcss-loader": "^7.3.3",
"postcss-preset-env": "^9.1.1",

228
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

1584
rs/0.1.0-alpha.7/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
[package]
name = "verifier"
version = "0.1.0"
license = "ISC"
edition = "2021"
exclude = ["index.node"]
[lib]
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4"
neon = "1"
elliptic-curve = { version = "0.13.5", features = ["pkcs8"] }
k256 = { version = "0.13", features = ["pem", "ecdsa"] }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0"
hex = "0.4"
bincode = { version = "1.3" }
tlsn-core = { git = "https://github.com/tlsnotary/tlsn.git", tag = "v0.1.0-alpha.7", package = "tlsn-core" }

119
rs/0.1.0-alpha.7/README.md Normal file
View File

@@ -0,0 +1,119 @@
# verifier
This project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
## Installing verifier
Installing verifier requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).
You can install the project with npm. In the project directory, run:
```sh
$ npm install
```
This fully installs the project, including installing any dependencies and running the build.
## Building verifier
If you have already installed the project and only want to run the build, run:
```sh
$ npm run build
```
This command uses the [cargo-cp-artifact](https://github.com/neon-bindings/cargo-cp-artifact) utility to run the Rust build and copy the built library into `./index.node`.
## Exploring verifier
After building verifier, you can explore its exports at the Node REPL:
```sh
$ npm install
$ node
> require('.').hello()
"hello node"
```
## Available Scripts
In the project directory, you can run:
### `npm install`
Installs the project, including running `npm run build`.
### `npm build`
Builds the Node addon (`index.node`) from source.
Additional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm build` and `npm build-*` commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):
```
npm run build -- --feature=beetle
```
#### `npm build-debug`
Alias for `npm build`.
#### `npm build-release`
Same as [`npm build`](#npm-build) but, builds the module with the [`release`](https://doc.rust-lang.org/cargo/reference/profiles.html#release) profile. Release builds will compile slower, but run faster.
### `npm test`
Runs the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).
## Project Layout
The directory structure of this project is:
```
verifier/
├── Cargo.toml
├── README.md
├── index.node
├── package.json
├── src/
| └── lib.rs
└── target/
```
### Cargo.toml
The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.
### README.md
This file.
### index.node
The Node addon—i.e., a binary Node module—generated by building the project. This is the main module for this package, as dictated by the `"main"` key in `package.json`.
Under the hood, a [Node addon](https://nodejs.org/api/addons.html) is a [dynamically-linked shared object](https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries). The `"build"` script produces this file by copying it from within the `target/` directory, which is where the Rust build produces the shared object.
### package.json
The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.
### src/
The directory tree containing the Rust source code for the project.
### src/lib.rs
The Rust library's main module.
### target/
Binary artifacts generated by the Rust build.
## Learn More
To learn more about Neon, see the [Neon documentation](https://neon-bindings.com).
To learn more about Rust, see the [Rust documentation](https://www.rust-lang.org).
To learn more about Node, see the [Node documentation](https://nodejs.org).

BIN
rs/0.1.0-alpha.7/index.node Executable file

Binary file not shown.

34
rs/0.1.0-alpha.7/package-lock.json generated Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "verifier",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "verifier",
"version": "0.1.0",
"hasInstallScript": true,
"license": "ISC",
"devDependencies": {
"cargo-cp-artifact": "^0.1"
}
},
"node_modules/cargo-cp-artifact": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.9.tgz",
"integrity": "sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==",
"dev": true,
"bin": {
"cargo-cp-artifact": "bin/cargo-cp-artifact.js"
}
}
},
"dependencies": {
"cargo-cp-artifact": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.9.tgz",
"integrity": "sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==",
"dev": true
}
}
}

View File

@@ -0,0 +1,18 @@
{
"name": "verifier",
"version": "0.1.0",
"description": "",
"main": "index.node",
"scripts": {
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
"build-debug": "npm run build --",
"build-release": "npm run build -- --release",
"install": "npm run build-release",
"test": "cargo test"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cargo-cp-artifact": "^0.1"
}
}

File diff suppressed because one or more lines are too long

133
rs/0.1.0-alpha.7/src/lib.rs Normal file
View File

@@ -0,0 +1,133 @@
use k256::pkcs8::DecodePublicKey;
use neon::prelude::*;
use tlsn_core::{
presentation::{Presentation, PresentationOutput},
signing::VerifyingKey,
CryptoProvider,
};
fn verify(mut cx: FunctionContext) -> JsResult<JsObject> {
let presentation_cx = cx.argument::<JsString>(0)?.value(&mut cx);
let notary_key_cx = cx.argument::<JsString>(1)?.value(&mut cx);
let (sent, recv, time) =
verify_presentation(presentation_cx, notary_key_cx).or_else(|e| cx.throw_error(e))?;
let obj: Handle<JsObject> = cx.empty_object();
let sent_str = cx.string(sent);
obj.set(&mut cx, "sent", sent_str)?;
let recv_str = cx.string(recv);
obj.set(&mut cx, "recv", recv_str)?;
let session_time = cx.number(time as f64);
obj.set(&mut cx, "time", session_time)?;
Ok(obj)
}
fn verify_presentation(
presentation_cx: String,
notary_key_cx: String,
) -> Result<(String, String, u64), String> {
// Deserialize the presentation
let bytes: Vec<u8> = hex::decode(presentation_cx.as_str()).map_err(|e| e.to_string())?;
let presentation: Presentation = bincode::deserialize(&bytes).map_err(|e| e.to_string())?;
// Verify the session proof against the Notary's public key
let VerifyingKey {
alg: _,
data: key_data,
} = presentation.verifying_key();
let notary_key = k256::PublicKey::from_public_key_pem(notary_key_cx.as_str())
.map_err(|x| format!("Invalid notary key: {}", x))?;
let verifying_key = k256::PublicKey::from_sec1_bytes(key_data)
.map_err(|x| format!("Invalid verifying key: {}", x))?;
if notary_key != verifying_key {
Err("The verifying key does not match the notary key")?;
}
// Verify the presentation.
let provider = CryptoProvider::default();
let PresentationOutput {
connection_info,
transcript,
..
} = presentation
.verify(&provider)
.map_err(|x| format!("Presentation verification failed: {}", x))?;
let (sent, recv) = transcript
.map(|mut partial_transcript| {
// Set the unauthenticated bytes so they are distinguishable.
partial_transcript.set_unauthed(b'X');
let sent = String::from_utf8_lossy(partial_transcript.sent_unsafe()).to_string();
let recv = String::from_utf8_lossy(partial_transcript.received_unsafe()).to_string();
(sent, recv)
})
.unwrap_or_default();
Ok((sent, recv, connection_info.time))
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("verify", verify)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Presentation {
version: String,
data: String,
}
/// get example presentation from example.com for testing
fn example_presentation() -> String {
let example = include_str!("example.json");
let presentation: Presentation = serde_json::from_str(&example).unwrap();
assert_eq!("0.1.0-alpha.7", presentation.version);
presentation.data
}
#[test]
fn test_verify() {
let notary_key_cx = String::from(
"-----BEGIN PUBLIC KEY-----
MDYwEAYHKoZIzj0CAQYFK4EEAAoDIgADe0jxnBObaIj7Xjg6TXLCM1GG/VhY5650
OrS/jgcbBuc=
-----END PUBLIC KEY-----",
);
let (sent, recv, time) =
verify_presentation(example_presentation(), notary_key_cx).unwrap();
assert_eq!(1728416631, time);
assert!(sent.contains("host: example.com"));
assert!(sent.contains("XXXXXXXXXXXXXXXXXX"));
assert!(recv.contains("<title>Example Domain</title>"));
assert!(recv.contains("Date: Tue, 08 Oct 2024"));
}
#[test]
fn test_verify_wrong_key() {
let notary_key_cx = String::from(
"-----BEGIN PUBLIC KEY-----
MDYwEAYHKoZIzj0CAQYFK4EEAAoDIgADZT9nJiwhGESLjwQNnZ2MsZ1xwjGzvmhF
xFi8Vjzanlg=
-----END PUBLIC KEY-----",
);
let res = verify_presentation(example_presentation(), notary_key_cx);
assert_eq!(
res,
Err("The verifying key does not match the notary key".to_string())
);
}
}

View File

@@ -12,8 +12,9 @@ import configureAppStore, { AppRootState } from '../web/store';
// @ts-ignore
import { verify } from '../rs/verifier/index.node';
// @ts-ignore
import { verify as verifyV6 } from '../rs/0.1.0-alpha.6/index.node';
import { verify as verifyV7 } from '../rs/0.1.0-alpha.7/index.node';
import { Attestation } from '../web/utils/types/types';
import { convertNotaryWsToHttp } from '../web/utils';
const app = express();
const port = 3000;
@@ -97,19 +98,37 @@ app.get('/ipfs/:cid', async (req, res) => {
* redirect to root if verification fails
*/
if (!jsonProof.version && jsonProof.notaryUrl) {
const proof = await verify(
file,
await fetchPublicKeyFromNotary(jsonProof.notaryUrl),
);
const notaryPem = await fetchPublicKeyFromNotary(jsonProof.notaryUrl);
const proof = await verify(file, notaryPem);
proof.notaryUrl = jsonProof.notaryUrl;
storeConfig.proofs.ipfs[req.params.cid].proof = proof;
} else if (jsonProof.version === '1.0') {
const proof = await verifyV6(
jsonProof.data,
await fetchPublicKeyFromNotary(jsonProof.meta.notaryUrl),
);
storeConfig.proofs.ipfs[req.params.cid].proof = {
...proof,
version: '0.1.0-alpha.5',
notaryUrl: jsonProof.notaryUrl,
notaryKey: notaryPem,
};
} else if (jsonProof.version === '0.1.0-alpha.7') {
const notaryUrl = convertNotaryWsToHttp(jsonProof.meta.notaryUrl);
const notaryPem = await fetchPublicKeyFromNotary(notaryUrl);
const proof = await verifyV7(jsonProof.data, notaryPem);
proof.notaryUrl = jsonProof.meta.notaryUrl;
storeConfig.proofs.ipfs[req.params.cid].proof = proof;
storeConfig.proofs.ipfs[req.params.cid].proof = {
version: '0.1.0-alpha.7',
time: proof.time,
sent: proof.sent,
recv: proof.recv,
notaryUrl: notaryUrl,
websocketProxyUrl: jsonProof.meta.websocketProxyUrl,
notaryKey: Buffer.from(
notaryPem
.replace('-----BEGIN PUBLIC KEY-----', '')
.replace('-----END PUBLIC KEY-----', '')
.replace(/\n/g, ''),
'base64',
)
.slice(23)
.toString('hex'),
};
}
const store = configureAppStore(storeConfig);
@@ -205,11 +224,8 @@ app.listen(port, () => {
});
async function fetchPublicKeyFromNotary(notaryUrl: string) {
const res = await fetch(
notaryUrl.replace('localhost', '127.0.0.1') + '/info',
);
const res = await fetch(notaryUrl + '/info');
const json: any = await res.json();
if (!json.publicKey) throw new Error('invalid response');
return json.publicKey;
}

View File

@@ -7,7 +7,10 @@ import React, {
} from 'react';
import c from 'classnames';
import classNames from 'classnames';
import { Attestation, Proof as VerifiedProof } from '../../utils/types/types';
import {
Attestation,
AttestedData as VerifiedProof,
} from '../../utils/types/types';
import Modal, { ModalContent, ModalFooter, ModalHeader } from '../Modal';
import Icon from '../Icon';
import { useDispatch } from 'react-redux';
@@ -55,15 +58,15 @@ export default function ProofViewer(props: {
)}
<div className="flex flex-col px-2">
<div className="flex flex-row gap-2 items-center">
<TabLabel onClick={() => setTab('info')} active={tab === 'info'}>
Info
</TabLabel>
<TabLabel onClick={() => setTab('sent')} active={tab === 'sent'}>
Sent
</TabLabel>
<TabLabel onClick={() => setTab('recv')} active={tab === 'recv'}>
Recv
</TabLabel>
<TabLabel onClick={() => setTab('info')} active={tab === 'info'}>
Metadata
</TabLabel>
<div className="flex flex-row flex-grow items-center justify-end">
<button className="button" onClick={onClickShare}>
Share
@@ -73,15 +76,30 @@ export default function ProofViewer(props: {
</div>
<div className="flex flex-col flex-grow px-2">
{tab === 'info' && (
<div className="w-full bg-slate-100 text-slate-800 border p-2 text-xs break-all h-full outline-none font-mono">
<div>
<div>Notary URL:</div>
<div>
{props.proof.version === '1.0'
? props.proof.meta.notaryUrl
: props.proof.notaryUrl}
</div>
</div>
<div className="flex flex-col w-full bg-slate-100 text-slate-800 border p-2 text-xs break-all h-full outline-none font-mono gap-4">
<MetadataRow label="Version" value={props.verifiedProof.version} />
<MetadataRow
label="Notary URL"
value={props.verifiedProof.notaryUrl}
/>
{props.verifiedProof.websocketProxyUrl && (
<MetadataRow
label="Websocket Proxy URL"
value={props.verifiedProof.websocketProxyUrl}
/>
)}
{props.verifiedProof.verifierKey && (
<MetadataRow
label="Verifying Key"
value={props.verifiedProof.verifierKey}
/>
)}
{props.verifiedProof.notaryKey && (
<MetadataRow
label="Notary Key"
value={props.verifiedProof.notaryKey}
/>
)}
</div>
)}
{tab === 'sent' && (
@@ -103,6 +121,15 @@ export default function ProofViewer(props: {
);
}
function MetadataRow({ label, value }: { label: string; value: string }) {
return (
<div>
<div>{label}:</div>
<div className="text-sm font-semibold whitespace-pre-wrap">{value}</div>
</div>
);
}
function TabLabel(props: {
children: ReactNode;
onClick: MouseEventHandler;

View File

@@ -5,7 +5,7 @@ import { useDispatch } from 'react-redux';
import ProofViewer from '../ProofViewer';
import { FileDropdown } from '../FileDropdown';
import { PubkeyInput } from '../../pages/PubkeyInput';
import { Proof } from '../../utils/types/types';
import { AttestedData } from '../../utils/types/types';
import { File } from '@web-std/file';
import { verify } from '../../utils';
@@ -18,7 +18,7 @@ export default function SharedProof(): ReactElement {
const file = new File([JSON.stringify(proofData?.raw)], `${cid}.json`, {
type: 'text/plain',
});
const [verifiedProof, setVerifiedProof] = useState<Proof | null>(
const [verifiedProof, setVerifiedProof] = useState<AttestedData | null>(
proofData?.proof || null,
);

View File

@@ -3,7 +3,10 @@ import { useDispatch } from 'react-redux';
import { readFileAsync, safeParseJSON, verify } from '../../utils';
import FileUploadInput from '../../components/FileUploadInput';
import ProofViewer from '../../components/ProofViewer';
import { Attestation, Proof as VerifiedProof } from '../../utils/types/types';
import {
Attestation,
AttestedData as VerifiedProof,
} from '../../utils/types/types';
import { FileDropdown } from '../../components/FileDropdown';
import { PubkeyInput } from '../PubkeyInput';
@@ -25,6 +28,7 @@ export default function FileDrop(): ReactElement {
setVerifiedProof(resp);
setStep('result');
} catch (e: any) {
console.error(e);
if (e?.message !== 'Failed to fetch') {
setError(
typeof e === 'string'

View File

@@ -70,7 +70,7 @@ export function PubkeyInput(props: {
<div className="font-semibold text-sm cursor-default">
Please enter the notary key for{' '}
<span className="text-blue-500 italic font-normal">
{proof.version === '1.0' ? proof.meta.notaryUrl : proof.notaryUrl}
{proof.version === '0.1.0-alpha.7' ? proof.meta.notaryUrl : <></>}
</span>
:
</div>

View File

@@ -4,7 +4,7 @@ import type { Proof } from 'tlsn-js-v5/build/types';
import { useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal';
import { EXPLORER_URL } from '../utils/constants';
import { Attestation } from '../utils/types/types';
import { Attestation, AttestedData } from '../utils/types/types';
import { verify } from '../utils';
enum ActionType {
@@ -18,19 +18,14 @@ export type Action<payload = any> = {
meta?: any;
};
type ProofData = {
type AttestationData = {
raw: Attestation;
proof?: {
time: number;
sent: string;
recv: string;
notaryUrl: string;
};
proof?: AttestedData;
};
type State = {
ipfs: {
[cid: string]: ProofData;
[cid: string]: AttestationData;
};
};
@@ -66,7 +61,7 @@ export const fetchProofFromIPFS =
};
export const setIPFSProof = (
payload: ProofData & {
payload: AttestationData & {
cid: string;
},
) => ({
@@ -76,16 +71,11 @@ export const setIPFSProof = (
export default function proofs(
state = initState,
action: Action<{
cid: string;
raw: Proof;
proof: {
time: number;
sent: string;
recv: string;
notaryUrl: string;
};
}>,
action: Action<
AttestationData & {
cid: string;
}
>,
): State {
switch (action.type) {
case ActionType.SetIPFSProof:
@@ -104,7 +94,7 @@ export default function proofs(
}
}
export const useIPFSProof = (cid?: string): ProofData | null => {
export const useIPFSProof = (cid?: string): AttestationData | null => {
return useSelector((state: AppRootState) => {
if (!cid) return null;
return state.proofs.ipfs[cid] || null;

View File

@@ -1,5 +1,5 @@
import { AppRootState } from '.';
import type { Proof } from '../utils/types/types';
import type { AttestedData } from '../utils/types/types';
import { useSelector } from 'react-redux';
export enum ActionType {
@@ -8,7 +8,7 @@ export enum ActionType {
UploadFileSuccess = 'proofupload/uploadFileSuccess',
}
export const uploadFile = (fileName: string, proof: Proof) => ({
export const uploadFile = (fileName: string, proof: AttestedData) => ({
type: ActionType.AddFile,
payload: { fileName, proof },
});
@@ -31,8 +31,12 @@ export type Action<payload = any> = {
};
type State = {
proofs: { fileName: string; proof: Proof }[];
selectedProof?: { fileName: string; proof: Proof; ipfsCID?: string } | null;
proofs: { fileName: string; proof: AttestedData }[];
selectedProof?: {
fileName: string;
proof: AttestedData;
ipfsCID?: string;
} | null;
};
const initState: State = {

View File

@@ -1,5 +1,5 @@
import React, { ReactElement, useRef } from 'react';
import { Attestation, Proof } from './types/types';
import { Attestation, AttestedData } from './types/types';
export const readFileAsync = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
@@ -98,33 +98,50 @@ async function initTlsnJs() {
export async function verify(
attestation: Attestation,
pubKey: string,
): Promise<Proof> {
): Promise<AttestedData> {
let key = pubKey;
const { NotaryServer } = await import('tlsn-js');
await initTlsnJs();
switch (attestation.version) {
case undefined: {
const { verify } = await import('tlsn-js-v5');
key = key || (await NotaryServer.from(attestation.notaryUrl).publicKey());
return await verify(attestation, key);
}
case '1.0': {
const { TlsProof } = await import('tlsn-js');
console.log(Buffer.from(attestation.data, 'hex').toString('binary'));
await initTlsnJs();
key =
key ||
(await NotaryServer.from(attestation.meta.notaryUrl).publicKey());
const tlsProof = new TlsProof(attestation.data);
const data = await tlsProof.verify({
typ: 'P256',
key: key,
});
(await NotaryServer.from(attestation.notaryUrl).publicKey('pem'));
const data = await verify(attestation, key);
return {
sent: data.sent,
recv: data.recv,
time: data.time,
notaryUrl: attestation.meta.notaryUrl,
...data,
version: '0.1.0-alpha.5',
notaryUrl: attestation.notaryUrl,
notaryKey: key,
};
}
case '0.1.0-alpha.7': {
const { Presentation, Transcript } = await import('tlsn-js');
const tlsProof = new Presentation(attestation.data);
const data = await tlsProof.verify();
const transcript = new Transcript({
sent: data.transcript.sent,
recv: data.transcript.recv,
});
const vk = await tlsProof.verifyingKey();
const verifyingKey = Buffer.from(vk.data).toString('hex');
const notaryUrl = convertNotaryWsToHttp(attestation.meta.notaryUrl);
const publicKey = await new NotaryServer(notaryUrl).publicKey();
if (verifyingKey !== publicKey)
throw new Error(`Notary key doesn't match verifying key`);
return {
version: '0.1.0-alpha.7',
sent: transcript.sent(),
recv: transcript.recv(),
time: data.connection_info.time,
notaryUrl: notaryUrl,
notaryKey: publicKey,
websocketProxyUrl: attestation.meta.websocketProxyUrl,
verifierKey: verifyingKey,
};
}
}
@@ -132,6 +149,13 @@ export async function verify(
throw new Error('Invalid Proof');
}
export function convertNotaryWsToHttp(notaryWs: string) {
const { protocol, pathname, hostname } = new URL(notaryWs);
const p = protocol === 'wss:' ? 'https:' : 'http';
const path = pathname === '/' ? '' : pathname.replace('/notarize', '');
return p + '//' + hostname + path;
}
function defer(): {
promise: Promise<any>;
resolve: (args?: any) => any;

View File

@@ -1,8 +1,12 @@
export interface Proof {
export interface AttestedData {
version: '0.1.0-alpha.7' | '0.1.0-alpha.5';
time: number;
sent: string;
recv: string;
notaryUrl: string;
notaryKey: string;
websocketProxyUrl?: string;
verifierKey?: string;
}
export type AttestationV0 = {
@@ -13,7 +17,7 @@ export type AttestationV0 = {
};
export type AttestationV1 = {
version: '1.0';
version: '0.1.0-alpha.7';
data: string;
meta: {
notaryUrl: string;

View File

@@ -1,9 +1,9 @@
import * as Comlink from 'comlink';
import init, { Prover, NotarizedSession, TlsProof } from 'tlsn-js';
import init, { Prover, Attestation, Presentation } from 'tlsn-js';
Comlink.expose({
init,
Prover,
NotarizedSession,
TlsProof,
Attestation,
Presentation,
});