refactor(types): WithSig -> Signed

This commit is contained in:
oxalica 2024-09-13 03:30:02 -04:00
parent 73eb441a26
commit 93d1589730
7 changed files with 39 additions and 39 deletions

View file

@ -60,7 +60,7 @@ impl fmt::Display for UserKey {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct WithSig<T> { pub struct Signed<T> {
#[serde(with = "hex::serde")] #[serde(with = "hex::serde")]
pub sig: [u8; SIGNATURE_LENGTH], pub sig: [u8; SIGNATURE_LENGTH],
pub signee: Signee<T>, pub signee: Signee<T>,
@ -82,7 +82,7 @@ pub fn get_timestamp() -> u64 {
.as_secs() .as_secs()
} }
impl<T: Serialize> WithSig<T> { impl<T: Serialize> Signed<T> {
/// Sign the payload with the given `key`. /// Sign the payload with the given `key`.
pub fn sign( pub fn sign(
key: &SigningKey, key: &SigningKey,
@ -308,7 +308,7 @@ impl RichText {
} }
} }
pub type SignedChatMsg = WithSig<ChatPayload>; pub type SignedChatMsg = Signed<ChatPayload>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RoomMetadata { pub struct RoomMetadata {
@ -551,7 +551,7 @@ mod tests {
let mut fake_rng = rand::rngs::mock::StepRng::new(0x42, 1); let mut fake_rng = rand::rngs::mock::StepRng::new(0x42, 1);
let signing_key = SigningKey::from_bytes(&[0x42; 32]); let signing_key = SigningKey::from_bytes(&[0x42; 32]);
let timestamp = 0xDEAD_BEEF; let timestamp = 0xDEAD_BEEF;
let msg = WithSig::sign( let msg = Signed::sign(
&signing_key, &signing_key,
timestamp, timestamp,
&mut fake_rng, &mut fake_rng,
@ -568,7 +568,7 @@ mod tests {
]]; ]];
expect.assert_eq(&json); expect.assert_eq(&json);
let roundtrip_msg = serde_json::from_str::<WithSig<ChatPayload>>(&json).unwrap(); let roundtrip_msg = serde_json::from_str::<Signed<ChatPayload>>(&json).unwrap();
assert_eq!(roundtrip_msg, msg); assert_eq!(roundtrip_msg, msg);
roundtrip_msg.verify().unwrap(); roundtrip_msg.verify().unwrap();
} }

View file

@ -5,7 +5,7 @@ use std::{fs, io};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use blah_types::{ use blah_types::{
bitflags, get_timestamp, ChatPayload, CreateGroup, CreateRoomPayload, Id, MemberPermission, bitflags, get_timestamp, ChatPayload, CreateGroup, CreateRoomPayload, Id, MemberPermission,
RichText, RoomAttrs, RoomMember, RoomMemberList, ServerPermission, UserKey, WithSig, RichText, RoomAttrs, RoomMember, RoomMemberList, ServerPermission, Signed, UserKey,
}; };
use ed25519_dalek::pkcs8::spki::der::pem::LineEnding; use ed25519_dalek::pkcs8::spki::der::pem::LineEnding;
use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}; use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey};
@ -227,7 +227,7 @@ async fn main_api(api_url: Url, command: ApiCommand) -> Result<()> {
user: UserKey(key.verifying_key().to_bytes()), user: UserKey(key.verifying_key().to_bytes()),
}]), }]),
}); });
let payload = WithSig::sign(&key, get_timestamp(), &mut OsRng, payload)?; let payload = Signed::sign(&key, get_timestamp(), &mut OsRng, payload)?;
let ret = client let ret = client
.post(api_url.join("/room/create")?) .post(api_url.join("/room/create")?)
@ -249,10 +249,10 @@ async fn main_api(api_url: Url, command: ApiCommand) -> Result<()> {
room: Id(room), room: Id(room),
rich_text: RichText::from(text), rich_text: RichText::from(text),
}; };
let payload = WithSig::sign(&key, get_timestamp(), &mut OsRng, payload)?; let payload = Signed::sign(&key, get_timestamp(), &mut OsRng, payload)?;
let ret = client let ret = client
.post(api_url.join(&format!("/room/{room}/item"))?) .post(api_url.join(&format!("/room/{room}/msg"))?)
.json(&payload) .json(&payload)
.send() .send()
.await? .await?

View file

@ -8,7 +8,7 @@ use std::task::{Context, Poll};
use anyhow::{bail, Context as _, Result}; use anyhow::{bail, Context as _, Result};
use axum::extract::ws::{Message, WebSocket}; use axum::extract::ws::{Message, WebSocket};
use blah_types::{AuthPayload, SignedChatMsg, WithSig}; use blah_types::{AuthPayload, Signed, SignedChatMsg};
use futures_util::future::Either; use futures_util::future::Either;
use futures_util::stream::SplitSink; use futures_util::stream::SplitSink;
use futures_util::{stream_select, SinkExt as _, Stream, StreamExt}; use futures_util::{stream_select, SinkExt as _, Stream, StreamExt};
@ -113,7 +113,7 @@ pub async fn handle_ws(st: Arc<AppState>, ws: &mut WebSocket) -> Result<Infallib
.await .await
.context("authentication timeout")? .context("authentication timeout")?
.ok_or(StreamEnded)??; .ok_or(StreamEnded)??;
let auth = serde_json::from_str::<WithSig<AuthPayload>>(&payload)?; let auth = serde_json::from_str::<Signed<AuthPayload>>(&payload)?;
st.verify_signed_data(&auth)?; st.verify_signed_data(&auth)?;
st.db st.db

View file

@ -12,8 +12,8 @@ use axum::{Json, Router};
use axum_extra::extract::WithRejection as R; use axum_extra::extract::WithRejection as R;
use blah_types::{ use blah_types::{
ChatPayload, CreateGroup, CreatePeerChat, CreateRoomPayload, Id, MemberPermission, RoomAdminOp, ChatPayload, CreateGroup, CreatePeerChat, CreateRoomPayload, Id, MemberPermission, RoomAdminOp,
RoomAdminPayload, RoomAttrs, RoomMetadata, ServerPermission, SignedChatMsg, Signee, UserKey, RoomAdminPayload, RoomAttrs, RoomMetadata, ServerPermission, Signed, SignedChatMsg, Signee,
WithMsgId, WithSig, UserKey, WithMsgId,
}; };
use config::ServerConfig; use config::ServerConfig;
use ed25519_dalek::SIGNATURE_LENGTH; use ed25519_dalek::SIGNATURE_LENGTH;
@ -59,7 +59,7 @@ impl AppState {
} }
} }
fn verify_signed_data<T: Serialize>(&self, data: &WithSig<T>) -> Result<(), ApiError> { fn verify_signed_data<T: Serialize>(&self, data: &Signed<T>) -> Result<(), ApiError> {
let Ok(()) = data.verify() else { let Ok(()) = data.verify() else {
return Err(error_response!( return Err(error_response!(
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,

View file

@ -6,7 +6,7 @@ use axum::extract::{FromRef, FromRequest, FromRequestParts, Request};
use axum::http::{header, request, StatusCode}; use axum::http::{header, request, StatusCode};
use axum::response::{IntoResponse, Response}; use axum::response::{IntoResponse, Response};
use axum::{async_trait, Json}; use axum::{async_trait, Json};
use blah_types::{AuthPayload, UserKey, WithSig}; use blah_types::{AuthPayload, Signed, UserKey};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -95,7 +95,7 @@ impl From<rusqlite::Error> for ApiError {
/// Extractor for verified JSON payload. /// Extractor for verified JSON payload.
#[derive(Debug)] #[derive(Debug)]
pub struct SignedJson<T>(pub WithSig<T>); pub struct SignedJson<T>(pub Signed<T>);
#[async_trait] #[async_trait]
impl<S, T> FromRequest<S> for SignedJson<T> impl<S, T> FromRequest<S> for SignedJson<T>
@ -107,7 +107,7 @@ where
type Rejection = ApiError; type Rejection = ApiError;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let Json(data) = <Json<WithSig<T>> as FromRequest<S>>::from_request(req, state).await?; let Json(data) = <Json<Signed<T>> as FromRequest<S>>::from_request(req, state).await?;
let st = <Arc<AppState>>::from_ref(state); let st = <Arc<AppState>>::from_ref(state);
st.verify_signed_data(&data)?; st.verify_signed_data(&data)?;
Ok(Self(data)) Ok(Self(data))
@ -178,7 +178,7 @@ where
let st = <Arc<AppState>>::from_ref(state); let st = <Arc<AppState>>::from_ref(state);
let data = let data =
serde_json::from_slice::<WithSig<AuthPayload>>(auth.as_bytes()).map_err(|err| { serde_json::from_slice::<Signed<AuthPayload>>(auth.as_bytes()).map_err(|err| {
AuthRejection::Invalid(error_response!( AuthRejection::Invalid(error_response!(
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
"deserialization", "deserialization",

View file

@ -9,7 +9,7 @@ use anyhow::Result;
use blah_types::{ use blah_types::{
get_timestamp, AuthPayload, ChatPayload, CreateGroup, CreatePeerChat, CreateRoomPayload, Id, get_timestamp, AuthPayload, ChatPayload, CreateGroup, CreatePeerChat, CreateRoomPayload, Id,
MemberPermission, RichText, RoomAdminOp, RoomAdminPayload, RoomAttrs, RoomMember, MemberPermission, RichText, RoomAdminOp, RoomAdminPayload, RoomAttrs, RoomMember,
RoomMemberList, RoomMetadata, ServerPermission, SignedChatMsg, UserKey, WithMsgId, WithSig, RoomMemberList, RoomMetadata, ServerPermission, Signed, SignedChatMsg, UserKey, WithMsgId,
}; };
use blahd::{ApiError, AppState, Database, RoomList, RoomMsgs}; use blahd::{ApiError, AppState, Database, RoomList, RoomMsgs};
use ed25519_dalek::SigningKey; use ed25519_dalek::SigningKey;
@ -241,8 +241,8 @@ async fn smoke(server: Server) {
assert_eq!(got, exp); assert_eq!(got, exp);
} }
fn sign<T: Serialize>(key: &SigningKey, rng: &mut dyn RngCore, payload: T) -> WithSig<T> { fn sign<T: Serialize>(key: &SigningKey, rng: &mut dyn RngCore, payload: T) -> Signed<T> {
WithSig::sign(key, get_timestamp(), rng, payload).unwrap() Signed::sign(key, get_timestamp(), rng, payload).unwrap()
} }
fn auth(key: &SigningKey, rng: &mut impl RngCore) -> String { fn auth(key: &SigningKey, rng: &mut impl RngCore) -> String {

View file

@ -13,7 +13,7 @@ paths:
This endpoint is for server-side-event dispatching. This endpoint is for server-side-event dispatching.
Once connected, client must send a JSON text message of type Once connected, client must send a JSON text message of type
`WithSig-Auth` for authentication. `Signed-Auth` for authentication.
If server does not close it immediately, it means success. If server does not close it immediately, it means success.
Since OAPI does not support WebSocket interface, we use request and Since OAPI does not support WebSocket interface, we use request and
@ -88,7 +88,7 @@ paths:
in: header in: header
description: Optional proof of membership for private rooms. description: Optional proof of membership for private rooms.
schema: schema:
$ref: '#/components/schemas/WithSig-Auth' $ref: '#/components/schemas/Signed-Auth'
responses: responses:
200: 200:
@ -119,7 +119,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/WithSig-CreateRoom' $ref: '#/components/schemas/Signed-CreateRoom'
responses: responses:
200: 200:
@ -159,7 +159,7 @@ paths:
in: header in: header
description: Optional proof of membership for private rooms. description: Optional proof of membership for private rooms.
schema: schema:
$ref: '#/components/schemas/WithSig-Auth' $ref: '#/components/schemas/Signed-Auth'
responses: responses:
200: 200:
@ -185,7 +185,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/WithSig-RoomAdmin' $ref: '#/components/schemas/Signed-RoomAdmin'
responses: responses:
204: 204:
@ -244,7 +244,7 @@ paths:
in: header in: header
description: Optional proof of membership for private rooms. description: Optional proof of membership for private rooms.
schema: schema:
$ref: '#/components/schemas/WithSig-Auth' $ref: '#/components/schemas/Signed-Auth'
- name: top - name: top
in: query in: query
@ -284,7 +284,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/WithSig-Chat' $ref: '#/components/schemas/Signed-Chat'
responses: responses:
200: 200:
@ -325,7 +325,7 @@ paths:
required: true required: true
description: Proof of membership for private rooms. description: Proof of membership for private rooms.
schema: schema:
$ref: '#/components/schemas/WithSig-Auth' $ref: '#/components/schemas/Signed-Auth'
responses: responses:
204: 204:
@ -345,14 +345,14 @@ components:
schemas: schemas:
WSClientToServer: WSClientToServer:
anyOf: anyOf:
- $ref: '#/components/schemas/WithSig-Auth' - $ref: '#/components/schemas/Signed-Auth'
WSServerToClient: WSServerToClient:
anyOf: anyOf:
- type: object - type: object
properties: properties:
chat: chat:
$ref: '#/components/schemas/WithSig-Chat' $ref: '#/components/schemas/Signed-Chat'
- type: object - type: object
properties: properties:
@ -401,7 +401,7 @@ components:
type: integer type: integer
format: int64 format: int64
last_msg: last_msg:
$ref: '#/components/schemas/WithMsgId-WithSig-Chat' $ref: '#/components/schemas/WithMsgId-Signed-Chat'
last_seen_cid: last_seen_cid:
description: The `cid` of the last chat being marked as seen. description: The `cid` of the last chat being marked as seen.
type: string type: string
@ -440,7 +440,7 @@ components:
description: Room messages in reversed server-received time order. description: Room messages in reversed server-received time order.
type: array type: array
items: items:
$ref: '#/components/schemas/WithMsgId-WithSig-Chat' $ref: '#/components/schemas/WithMsgId-Signed-Chat'
skip_token: skip_token:
description: The token for fetching the next page. description: The token for fetching the next page.
type: string type: string
@ -481,7 +481,7 @@ components:
description: Link target. description: Link target.
WithSig-Auth: Signed-Auth:
type: object type: object
properties: properties:
sig: sig:
@ -499,7 +499,7 @@ components:
type: string type: string
const: 'auth' const: 'auth'
WithSig-RoomAdmin: Signed-RoomAdmin:
type: object type: object
properties: properties:
sig: sig:
@ -551,7 +551,7 @@ components:
timestamp: 1724966284 timestamp: 1724966284
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7 user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
WithSig-Chat: Signed-Chat:
type: object type: object
properties: properties:
sig: sig:
@ -583,16 +583,16 @@ components:
timestamp: 1724966284 timestamp: 1724966284
user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7 user: 83ce46ced47ec0391c64846cbb6c507250ead4985b6a044d68751edc46015dd7
WithMsgId-WithSig-Chat: WithMsgId-Signed-Chat:
allOf: allOf:
- $ref: '#/components/schemas/WithSig-Chat' - $ref: '#/components/schemas/Signed-Chat'
- type: object - type: object
properties: properties:
cid: cid:
type: string type: string
description: An opaque server-specific identifier. description: An opaque server-specific identifier.
WithSig-CreateRoom: Signed-CreateRoom:
type: object type: object
properties: properties:
sig: sig: