mirror of
https://github.com/ajvpot/meshexplorer.git
synced 2026-06-25 20:30:57 +02:00
support # channels
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import React, { createContext, useContext, useState, useEffect, useRef, useLayoutEffect, ReactNode } from "react";
|
||||
import { getChannelIdFromKey } from "@/lib/meshcore";
|
||||
import { getChannelIdFromKey, deriveKeyFromChannelName } from "@/lib/meshcore";
|
||||
import { getRegionFriendlyNames } from "@/lib/regions";
|
||||
import Modal from "./Modal";
|
||||
|
||||
@@ -353,7 +353,19 @@ function MeshcoreKeyModal({ config, setConfig, onClose }: { config: Config, setC
|
||||
value={key.channelName}
|
||||
onChange={e => {
|
||||
const updated = [...(config.meshcoreKeys || [])];
|
||||
updated[idx] = { ...updated[idx], channelName: e.target.value };
|
||||
const newChannelName = e.target.value;
|
||||
const updatedKey = { ...updated[idx], channelName: newChannelName };
|
||||
|
||||
// Auto-populate private key for # channels
|
||||
if (newChannelName.startsWith('#') && newChannelName.length > 1) {
|
||||
try {
|
||||
updatedKey.privateKey = deriveKeyFromChannelName(newChannelName);
|
||||
} catch (error) {
|
||||
// If derivation fails, leave the key as is
|
||||
}
|
||||
}
|
||||
|
||||
updated[idx] = updatedKey;
|
||||
setConfig({ ...config, meshcoreKeys: updated });
|
||||
}}
|
||||
/>
|
||||
@@ -373,7 +385,7 @@ function MeshcoreKeyModal({ config, setConfig, onClose }: { config: Config, setC
|
||||
<input
|
||||
className={`flex-1 p-1 border rounded font-mono ${keyError ? 'border-red-500' : ''}`}
|
||||
type="text"
|
||||
placeholder="Base64 or Hex Private Key"
|
||||
placeholder="Base64 or Hex Private Key (auto-filled for # channels)"
|
||||
value={key.privateKey}
|
||||
onChange={e => {
|
||||
const updated = [...(config.meshcoreKeys || [])];
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
import { createHash, createHmac } from "crypto";
|
||||
import aesjs from "aes-js";
|
||||
|
||||
/**
|
||||
* Derives a 128-bit encryption key from a channel name that starts with '#'.
|
||||
* Applies filtering: converts to lowercase and keeps only a-z, 0-9, and hyphen.
|
||||
* Uses SHA256 hash of the filtered channel name (including '#') as ASCII bytes,
|
||||
* then truncates to first 128 bits (16 bytes) and returns as hex.
|
||||
*/
|
||||
export function deriveKeyFromChannelName(channelName: string): string {
|
||||
if (!channelName.startsWith('#')) {
|
||||
throw new Error('Channel name must start with #');
|
||||
}
|
||||
|
||||
// Apply filtering: lowercase and keep only a-z, 0-9, hyphen
|
||||
const filteredName = '#' + channelName.slice(1)
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9-]/g, '');
|
||||
|
||||
// Convert filtered channel name to ASCII bytes and hash with SHA256
|
||||
const nameBytes = Buffer.from(filteredName, 'ascii');
|
||||
const hash = createHash('sha256').update(nameBytes).digest();
|
||||
|
||||
// Truncate to first 128 bits (16 bytes) and return as hex
|
||||
const key128bit = hash.slice(0, 16);
|
||||
return key128bit.toString('hex');
|
||||
}
|
||||
|
||||
// Module-level cache for channel IDs
|
||||
const channelIdCache: Record<string, string> = {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user