login lib -> signer lib

This commit is contained in:
polwex 2025-03-20 01:11:49 +07:00
parent 50d5f9f387
commit b4aaea6598
15 changed files with 845 additions and 536 deletions

View File

@ -1,6 +0,0 @@
interface all {}
world login-sys-v0 {
import all;
include process-v1;
}

View File

@ -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.

View File

@ -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
}
]

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = [ members = [
"login", "sign",
] ]
[profile.release] [profile.release]

View 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;
}

View File

@ -1,9 +1,9 @@
{ {
"name": "Login", "name": "Sign",
"description": "Login with Hyperware", "description": "Sign messages with Hyperware",
"image": "", "image": "",
"properties": { "properties": {
"package_name": "login", "package_name": "sign",
"current_version": "1.0.0", "current_version": "1.0.0",
"publisher": "sys", "publisher": "sys",
"mirrors": [], "mirrors": [],

BIN
signer/pkg/api.zip Normal file

Binary file not shown.

11
signer/pkg/manifest.json Normal file
View 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

Binary file not shown.

View File

@ -1,5 +1,5 @@
[package] [package]
name = "login" name = "sign"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
@ -8,7 +8,7 @@ simulation-mode = []
[dependencies] [dependencies]
anyhow = "1.0.97" anyhow = "1.0.97"
hyperware_process_lib = "1.0.3" hyperware_process_lib = {version = "1.0.4", features = ["logging"]}
process_macros = "0.1" process_macros = "0.1"
rmp-serde = "1.3.0" rmp-serde = "1.3.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

98
signer/sign/src/lib.rs Normal file
View 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")),
}
}