mirror of
https://github.com/xtr-dev/rondevu-server.git
synced 2025-12-09 18:33:24 +00:00
fix: add validateServicePublish for correct signature verification
The service publishing endpoint was using validateUsernameClaim which
expects the message format "claim:{username}:{timestamp}", but clients
send "publish:{username}:{serviceFqn}:{timestamp}".
Added validateServicePublish function to properly validate service
publishing signatures with the correct message format.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/rondevu-server",
|
"name": "@xtr-dev/rondevu-server",
|
||||||
"version": "0.2.3",
|
"version": "0.2.4",
|
||||||
"description": "DNS-like WebRTC signaling server with username claiming and service discovery",
|
"description": "DNS-like WebRTC signaling server with username claiming and service discovery",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { cors } from 'hono/cors';
|
|||||||
import { Storage } from './storage/types.ts';
|
import { Storage } from './storage/types.ts';
|
||||||
import { Config } from './config.ts';
|
import { Config } from './config.ts';
|
||||||
import { createAuthMiddleware, getAuthenticatedPeerId } from './middleware/auth.ts';
|
import { createAuthMiddleware, getAuthenticatedPeerId } from './middleware/auth.ts';
|
||||||
import { generatePeerId, encryptPeerId, validateUsernameClaim, validateServiceFqn } from './crypto.ts';
|
import { generatePeerId, encryptPeerId, validateUsernameClaim, validateServicePublish, validateServiceFqn } from './crypto.ts';
|
||||||
import type { Context } from 'hono';
|
import type { Context } from 'hono';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,7 +207,7 @@ export function createApp(storage: Storage, config: Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify signature matches username's public key
|
// Verify signature matches username's public key
|
||||||
const signatureValidation = await validateUsernameClaim(username, usernameRecord.publicKey, signature, message);
|
const signatureValidation = await validateServicePublish(username, serviceFqn, usernameRecord.publicKey, signature, message);
|
||||||
if (!signatureValidation.valid) {
|
if (!signatureValidation.valid) {
|
||||||
return c.json({ error: 'Invalid signature for username' }, 403);
|
return c.json({ error: 'Invalid signature for username' }, 403);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,3 +317,46 @@ export async function validateUsernameClaim(
|
|||||||
|
|
||||||
return { valid: true };
|
return { valid: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a service publish signature
|
||||||
|
* Message format: publish:{username}:{serviceFqn}:{timestamp}
|
||||||
|
*/
|
||||||
|
export async function validateServicePublish(
|
||||||
|
username: string,
|
||||||
|
serviceFqn: string,
|
||||||
|
publicKey: string,
|
||||||
|
signature: string,
|
||||||
|
message: string
|
||||||
|
): Promise<{ valid: boolean; error?: string }> {
|
||||||
|
// Validate username format
|
||||||
|
const usernameCheck = validateUsername(username);
|
||||||
|
if (!usernameCheck.valid) {
|
||||||
|
return usernameCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse message format: "publish:{username}:{serviceFqn}:{timestamp}"
|
||||||
|
const parts = message.split(':');
|
||||||
|
if (parts.length !== 4 || parts[0] !== 'publish' || parts[1] !== username || parts[2] !== serviceFqn) {
|
||||||
|
return { valid: false, error: 'Invalid message format (expected: publish:{username}:{serviceFqn}:{timestamp})' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = parseInt(parts[3], 10);
|
||||||
|
if (isNaN(timestamp)) {
|
||||||
|
return { valid: false, error: 'Invalid timestamp in message' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate timestamp
|
||||||
|
const timestampCheck = validateTimestamp(timestamp);
|
||||||
|
if (!timestampCheck.valid) {
|
||||||
|
return timestampCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify signature
|
||||||
|
const signatureValid = await verifyEd25519Signature(publicKey, signature, message);
|
||||||
|
if (!signatureValid) {
|
||||||
|
return { valid: false, error: 'Invalid signature' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { valid: true };
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user