Compare commits
2 Commits
cd4bf0c99e
...
b4aaea6598
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b4aaea6598 | ||
![]() |
50d5f9f387 |
@ -29,6 +29,15 @@ wit_bindgen::generate!({
|
||||
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto],
|
||||
});
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum SignerRequest {
|
||||
Sign,
|
||||
Verify { node: String, signature: Vec<u8> },
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeJsonInto)]
|
||||
struct SignResponse {
|
||||
signature: Vec<u8>,
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum FrontendRequest {
|
||||
Sign,
|
||||
@ -37,22 +46,11 @@ enum FrontendRequest {
|
||||
Debug(String),
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum SignerRequest {
|
||||
Sign(SignRequest),
|
||||
Verify { from: Address, data: SignResponse },
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct SignRequest {
|
||||
struct LoginMessage {
|
||||
pub site: String,
|
||||
pub time: u64,
|
||||
pub nonce: Option<String>,
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeJsonInto)]
|
||||
struct SignResponse {
|
||||
pub body: SignRequest,
|
||||
pub message: Vec<u8>,
|
||||
pub signature: Vec<u8>,
|
||||
}
|
||||
const ICON: &str = include_str!("icon");
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@ -94,6 +92,35 @@ impl VersionedState {
|
||||
}
|
||||
}
|
||||
|
||||
fn _signer_test(our: &Address) -> anyhow::Result<()> {
|
||||
let target = Address::new(our.node(), ("sign", "sign", "sys"));
|
||||
let login_message = LoginMessage {
|
||||
site: WEB2_URL.to_string(),
|
||||
nonce: Some(WEB2_LOGIN_NONCE.to_string()),
|
||||
time: get_now(),
|
||||
};
|
||||
let blob = serde_json::to_vec(&login_message)?;
|
||||
// Get the signature from login:sys:sys
|
||||
let res: SignResponse = Request::to(target.clone())
|
||||
.blob_bytes(blob.clone())
|
||||
.body(serde_json::to_vec(&SignerRequest::Sign)?)
|
||||
.send_and_await_response(10)??
|
||||
.body()
|
||||
.try_into()?;
|
||||
// Send signature to designated endpoint on Web2 app
|
||||
let body2 = SignerRequest::Verify {
|
||||
node: our.node().to_string(),
|
||||
signature: res.signature,
|
||||
};
|
||||
let verify_res = Request::to(target)
|
||||
.blob_bytes(blob)
|
||||
.body(serde_json::to_vec(&body2)?)
|
||||
.send_and_await_response(10)??;
|
||||
let is_good: bool = serde_json::from_slice(verify_res.body())?;
|
||||
kiprintln!("verify_res \n{:#?}", is_good);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
call_init!(initialize);
|
||||
fn initialize(our: Address) {
|
||||
init_logging(Level::DEBUG, Level::INFO, None, None, None).unwrap();
|
||||
@ -115,12 +142,6 @@ fn initialize(our: Address) {
|
||||
http_server
|
||||
.bind_ws_path("/", WsBindingConfig::default())
|
||||
.unwrap();
|
||||
// let http_config = HttpBindingConfig::default().secure_subdomain(true);
|
||||
|
||||
// http_server
|
||||
// .serve_ui("ui", vec!["/hypr-login"], http_config.clone())
|
||||
// .expect("Failed to serve UI");
|
||||
// http_server.secure_bind_http_path("/").unwrap();
|
||||
|
||||
main_loop(&our, &mut state, &mut http_server);
|
||||
}
|
||||
@ -207,15 +228,17 @@ fn handle_login_request(
|
||||
let request = serde_json::from_slice::<FrontendRequest>(request_bytes)?;
|
||||
match request {
|
||||
FrontendRequest::Sign => {
|
||||
let target = Address::new(our.node(), ("login", "login", "sys"));
|
||||
let lr = SignerRequest::Sign(SignRequest {
|
||||
let target = Address::new(our.node(), ("sign", "sign", "sys"));
|
||||
let body = LoginMessage {
|
||||
site: WEB2_URL.to_string(),
|
||||
nonce: Some(WEB2_LOGIN_NONCE.to_string()),
|
||||
time: get_now(),
|
||||
});
|
||||
};
|
||||
let body_bytes = serde_json::to_vec(&body)?;
|
||||
// Get the signature from login:sys:sys
|
||||
let res: SignResponse = Request::to(target)
|
||||
.body(serde_json::to_vec(&lr)?)
|
||||
.blob_bytes(body_bytes)
|
||||
.body(serde_json::to_vec(&SignerRequest::Sign)?)
|
||||
.send_and_await_response(10)??
|
||||
.body()
|
||||
.try_into()?;
|
||||
@ -255,7 +278,8 @@ fn attempt_login(
|
||||
let mut json_headers = HashMap::new();
|
||||
json_headers.insert("Content-type".to_string(), "application/json".to_string());
|
||||
let node = our.node();
|
||||
let message = signature_response.message;
|
||||
let blob = get_blob().ok_or(anyhow::anyhow!("no blob"))?;
|
||||
let message = blob.bytes();
|
||||
let signature = signature_response.signature;
|
||||
let json =
|
||||
serde_json::to_vec(&json!({"node":node, "message": message, "signature": signature}))?;
|
||||
|
@ -227,6 +227,7 @@ fn mother_script(prefix: &str) -> String {
|
||||
<script>
|
||||
const HYPERWARE_APP_PATH = '{0}';
|
||||
</script>
|
||||
<script src="./proxy.js" />
|
||||
"#,
|
||||
prefix
|
||||
);
|
||||
|
Binary file not shown.
Binary file not shown.
@ -8,14 +8,14 @@
|
||||
"homepage:homepage:sys",
|
||||
"http-server:distro:sys",
|
||||
"http-client:distro:sys",
|
||||
"login:login:sys",
|
||||
"sign:sign:sys",
|
||||
"vfs:distro:sys"
|
||||
],
|
||||
"grant_capabilities": [
|
||||
"homepage:homepage:sys",
|
||||
"http-server:distro:sys",
|
||||
"http-client:distro:sys",
|
||||
"login:login:sys",
|
||||
"sign:sign:sys",
|
||||
"vfs:distro:sys"
|
||||
],
|
||||
"public": false
|
||||
|
@ -1,6 +0,0 @@
|
||||
interface all {}
|
||||
|
||||
world login-sys-v0 {
|
||||
import all;
|
||||
include process-v1;
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
use crate::hyperware::process;
|
||||
use anyhow::{anyhow, Result};
|
||||
use hyperware::process::standard::send_response;
|
||||
use hyperware_process_lib::net::{NetAction, NetResponse};
|
||||
use hyperware_process_lib::{
|
||||
await_message, call_init, eth, get_blob, get_typed_state, homepage, http, hypermap, kiprintln,
|
||||
set_state, Address, Capability, LazyLoadBlob, Message, NodeId, Request, Response,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
wit_bindgen::generate!({
|
||||
path: "target/wit",
|
||||
world: "login-sys-v0",
|
||||
generate_unused_types: true,
|
||||
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto],
|
||||
});
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct LoginStateV1 {
|
||||
our: Address,
|
||||
apps: HashMap<NodeId, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
enum LoginRequest {
|
||||
Sign(SignRequest),
|
||||
Verify { from: Address, data: SignResponse },
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct SignRequest {
|
||||
pub site: String,
|
||||
pub time: u64,
|
||||
pub nonce: Option<String>,
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct SignResponse {
|
||||
pub body: SignRequest,
|
||||
pub message: Vec<u8>,
|
||||
pub signature: Vec<u8>,
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "version")]
|
||||
enum VersionedState {
|
||||
/// State fully stored in memory, persisted using serde_json.
|
||||
/// Future state version will use SQLite.
|
||||
V1(LoginStateV1),
|
||||
}
|
||||
|
||||
impl VersionedState {
|
||||
fn load(our: Address) -> Self {
|
||||
get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self::V1(LoginStateV1 {
|
||||
our,
|
||||
apps: HashMap::new(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn save(&self) {
|
||||
set_state(&serde_json::to_vec(&self).expect("Failed to serialize contacts state!"));
|
||||
}
|
||||
}
|
||||
|
||||
call_init!(initialize);
|
||||
fn initialize(our: Address) {
|
||||
let mut state = VersionedState::load(our.clone());
|
||||
loop {
|
||||
let msg = await_message();
|
||||
match msg {
|
||||
Err(_send_error) => {
|
||||
// ignore send errors, local-only process
|
||||
continue;
|
||||
}
|
||||
Ok(Message::Request {
|
||||
source,
|
||||
body,
|
||||
capabilities,
|
||||
..
|
||||
}) => {
|
||||
handle_request(&our, &source, &mut state, &body, capabilities).unwrap_or_default()
|
||||
}
|
||||
_ => continue, // ignore responses
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_request(
|
||||
our: &Address,
|
||||
source: &Address,
|
||||
state: &mut VersionedState,
|
||||
request_bytes: &[u8],
|
||||
capabilities: Vec<Capability>,
|
||||
) -> Result<()> {
|
||||
let req = serde_json::from_slice::<LoginRequest>(request_bytes)?;
|
||||
match req {
|
||||
LoginRequest::Sign(r) => handle_sign(our, r, request_bytes),
|
||||
LoginRequest::Verify { from, data } => handle_verify(from, data),
|
||||
}
|
||||
}
|
||||
|
||||
// let message = [
|
||||
// from.to_string().as_bytes(),
|
||||
// &km.lazy_load_blob
|
||||
// .as_ref()
|
||||
// .unwrap_or(&lib::core::LazyLoadBlob {
|
||||
// mime: None,
|
||||
// bytes: vec![],
|
||||
// })
|
||||
// .bytes,
|
||||
// ]
|
||||
// .concat();
|
||||
// pub fn validate_signature(from: &str, signature: &[u8], message: &[u8], pki: &OnchainPKI) -> bool {
|
||||
// if let Some(peer_id) = pki.get(from) {
|
||||
// let their_networking_key = signature::UnparsedPublicKey::new(
|
||||
// &signature::ED25519,
|
||||
// net_key_string_to_hex(&peer_id.networking_key),
|
||||
// );
|
||||
// their_networking_key.verify(message, signature).is_ok()
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
|
||||
fn handle_sign(our: &Address, req: SignRequest, request_bytes: &[u8]) -> Result<()> {
|
||||
let body = rmp_serde::to_vec(&NetAction::Sign)?;
|
||||
let res = Request::to(("our", "net", "distro", "sys"))
|
||||
.blob_bytes(request_bytes)
|
||||
.body(body)
|
||||
.send_and_await_response(10)??;
|
||||
let Ok(NetResponse::Signed) = rmp_serde::from_slice::<NetResponse>(res.body()) else {
|
||||
return Err(anyhow!("signature failed"));
|
||||
};
|
||||
let newblob = res.blob();
|
||||
let message = [our.to_string().as_bytes(), request_bytes].concat();
|
||||
match newblob {
|
||||
None => Err(anyhow!("no blob")),
|
||||
Some(b) => {
|
||||
let lr = SignResponse {
|
||||
body: req,
|
||||
message,
|
||||
signature: b.bytes().to_vec(),
|
||||
};
|
||||
let lrj = serde_json::to_vec(&lr)?;
|
||||
Response::new().body(lrj).send()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
fn handle_verify(from: Address, data: SignResponse) -> Result<()> {
|
||||
let signature = data.signature;
|
||||
let body = rmp_serde::to_vec(&NetAction::Verify { from, signature })?;
|
||||
let req_bytes = rmp_serde::to_vec(&data.body)?;
|
||||
let res = Request::to(("our", "net", "distro", "sys"))
|
||||
.blob_bytes(req_bytes)
|
||||
.body(body)
|
||||
.send_and_await_response(10)??;
|
||||
let resp = rmp_serde::from_slice::<NetResponse>(res.body())?;
|
||||
match resp {
|
||||
NetResponse::Verified(is_good) => {
|
||||
Response::new().body(serde_json::to_vec(&is_good)?).send()?;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(anyhow!("weird response")),
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -1,11 +0,0 @@
|
||||
[
|
||||
{
|
||||
"process_name": "login",
|
||||
"process_wasm_path": "/login.wasm",
|
||||
"on_exit": "Restart",
|
||||
"request_networking": false,
|
||||
"request_capabilities": ["net:distro:sys"],
|
||||
"grant_capabilities": ["net:distro:sys"],
|
||||
"public": false
|
||||
}
|
||||
]
|
1055
login/Cargo.lock → signer/Cargo.lock
generated
1055
login/Cargo.lock → signer/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"login",
|
||||
"sign",
|
||||
]
|
||||
|
||||
[profile.release]
|
23
signer/api/sign:sys-v0.wit
Normal file
23
signer/api/sign:sys-v0.wit
Normal file
@ -0,0 +1,23 @@
|
||||
interface sign{
|
||||
use standard.{address};
|
||||
|
||||
// takes blob for message to sign or verify
|
||||
variant request{
|
||||
sign,
|
||||
verify(verify-request)
|
||||
}
|
||||
// takes blob
|
||||
record verify-request{
|
||||
node: string,
|
||||
signature: list<u8>
|
||||
}
|
||||
// takes blob
|
||||
record sign-response{
|
||||
signature: list<u8>
|
||||
}
|
||||
}
|
||||
|
||||
world sign-sys-v0 {
|
||||
import sign;
|
||||
include process-v1;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "Login",
|
||||
"description": "Login with Hyperware",
|
||||
"name": "Sign",
|
||||
"description": "Sign messages with Hyperware",
|
||||
"image": "",
|
||||
"properties": {
|
||||
"package_name": "login",
|
||||
"package_name": "sign",
|
||||
"current_version": "1.0.0",
|
||||
"publisher": "sys",
|
||||
"mirrors": [],
|
BIN
signer/pkg/api.zip
Normal file
BIN
signer/pkg/api.zip
Normal file
Binary file not shown.
11
signer/pkg/manifest.json
Normal file
11
signer/pkg/manifest.json
Normal file
@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"process_name": "sign",
|
||||
"process_wasm_path": "/sign.wasm",
|
||||
"on_exit": "Restart",
|
||||
"request_networking": false,
|
||||
"request_capabilities": ["net:distro:sys", "vfs:distro:sys"],
|
||||
"grant_capabilities": ["net:distro:sys", "vfs:distro:sys"],
|
||||
"public": false
|
||||
}
|
||||
]
|
BIN
signer/pkg/sign.wasm
Normal file
BIN
signer/pkg/sign.wasm
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "login"
|
||||
name = "sign"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@ -8,7 +8,7 @@ simulation-mode = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.97"
|
||||
hyperware_process_lib = "1.0.3"
|
||||
hyperware_process_lib = {version = "1.0.4", features = ["logging"]}
|
||||
process_macros = "0.1"
|
||||
rmp-serde = "1.3.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
98
signer/sign/src/lib.rs
Normal file
98
signer/sign/src/lib.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use crate::hyperware::process::sign;
|
||||
use anyhow::{anyhow, Result};
|
||||
use hyperware_process_lib::logging::{error, init_logging, Level};
|
||||
use hyperware_process_lib::net::{NetAction, NetResponse};
|
||||
use hyperware_process_lib::{
|
||||
await_message, call_init, get_blob, kiprintln, Address, Message, Request, Response,
|
||||
};
|
||||
|
||||
wit_bindgen::generate!({
|
||||
path: "target/wit",
|
||||
world: "sign-sys-v0",
|
||||
generate_unused_types: true,
|
||||
additional_derives: [PartialEq, serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto],
|
||||
});
|
||||
|
||||
call_init!(initialize);
|
||||
fn initialize(our: Address) {
|
||||
// this seems to require calling vfs:distro:sys
|
||||
init_logging(Level::DEBUG, Level::INFO, None, None, None).unwrap();
|
||||
loop {
|
||||
match await_message() {
|
||||
Err(send_error) => error!("got SendError: {send_error}"),
|
||||
Ok(ref message) => {
|
||||
match message {
|
||||
Message::Request { body, .. } => match handle_request(&our, &body) {
|
||||
Ok(_) => continue,
|
||||
Err(request_error) => {
|
||||
error!("error handling sign request: \n{request_error}")
|
||||
}
|
||||
},
|
||||
_ => error!("Response received at sign process"), // we are awaiting all requests no resposes should be received
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_request(our: &Address, request_bytes: &[u8]) -> Result<()> {
|
||||
match request_bytes.try_into()? {
|
||||
sign::Request::Sign => handle_sign(),
|
||||
sign::Request::Verify(req) => handle_verify(our, req),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_sign() -> Result<()> {
|
||||
let Some(blob) = get_blob() else {
|
||||
return Err(anyhow!("no blob"));
|
||||
};
|
||||
let body = rmp_serde::to_vec(&NetAction::Sign)?;
|
||||
let res = Request::to(("our", "net", "distro", "sys"))
|
||||
.blob(blob.clone())
|
||||
.body(body)
|
||||
.send_and_await_response(10)??;
|
||||
let Ok(NetResponse::Signed) = rmp_serde::from_slice::<NetResponse>(res.body()) else {
|
||||
return Err(anyhow!("signature failed"));
|
||||
};
|
||||
let signature = res.blob();
|
||||
match signature {
|
||||
None => Err(anyhow!("no blob")),
|
||||
Some(b) => {
|
||||
let sign_response = sign::SignResponse {
|
||||
signature: b.bytes().to_vec(),
|
||||
};
|
||||
let sign_response_bytes = serde_json::to_vec(&sign_response)?;
|
||||
Response::new()
|
||||
.blob(blob)
|
||||
.body(sign_response_bytes)
|
||||
.send()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE net:distro:sys prepends the node ID to every message before signing
|
||||
fn handle_verify(our: &Address, req: sign::VerifyRequest) -> Result<()> {
|
||||
kiprintln!("handling verifyy");
|
||||
let Some(blob) = get_blob() else {
|
||||
return Err(anyhow!("no blob"));
|
||||
};
|
||||
let process = our.to_owned().process;
|
||||
let from = Address::new(req.node, process);
|
||||
kiprintln!("handling verify");
|
||||
let body = rmp_serde::to_vec(&NetAction::Verify {
|
||||
from,
|
||||
signature: req.signature,
|
||||
})?;
|
||||
let res = Request::to(("our", "net", "distro", "sys"))
|
||||
.blob(blob)
|
||||
.body(body)
|
||||
.send_and_await_response(10)??;
|
||||
let resp = rmp_serde::from_slice::<NetResponse>(res.body())?;
|
||||
match resp {
|
||||
NetResponse::Verified(is_good) => {
|
||||
Response::new().body(serde_json::to_vec(&is_good)?).send()?;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(anyhow!("weird response")),
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user