11import bodyParser from "body-parser" ;
2- import express , { Request , Response } from "express" ;
3- import { BASE_ONION_ROUTER_PORT , REGISTRY_PORT } from "../config" ;
4- import { generateRsaKeyPair , exportPubKey , exportPrvKey } from "../crypto" ;
2+ import express from "express" ;
3+ import { BASE_ONION_ROUTER_PORT , REGISTRY_PORT , BASE_USER_PORT } from "../config" ;
4+ import {
5+ generateRsaKeyPair ,
6+ rsaDecrypt ,
7+ symDecrypt ,
8+ importSymKey ,
9+ exportPubKey ,
10+ exportPrvKey ,
11+ exportSymKey ,
12+ } from "../crypto" ;
513import { webcrypto } from "node:crypto" ;
614
715type CK = webcrypto . CryptoKey ;
@@ -15,8 +23,7 @@ export async function simpleOnionRouter(nodeId: number) {
1523 let publicKey : CK ;
1624 let privateKeyStr : string ;
1725 let publicKeyStr : string ;
18-
19- // Store the last received messages and destination (default: null)
26+ let lastCircuit : number [ ] = [ ] ;
2027 let lastReceivedEncryptedMessage : string | null = null ;
2128 let lastReceivedDecryptedMessage : string | null = null ;
2229 let lastMessageDestination : number | null = null ;
@@ -25,56 +32,80 @@ export async function simpleOnionRouter(nodeId: number) {
2532 const keyPair = await generateRsaKeyPair ( ) ;
2633 privateKey = keyPair . privateKey ;
2734 publicKey = keyPair . publicKey ;
28-
29- // Convert keys to base64
3035 publicKeyStr = await exportPubKey ( publicKey ) ;
3136 privateKeyStr = await exportPrvKey ( privateKey ) ;
3237
33- // Register with the registry
34- const response = await fetch ( `http://localhost:${ REGISTRY_PORT } /registerNode` , {
38+ const registryResponse = await fetch ( `http://localhost:${ REGISTRY_PORT } /registerNode` , {
3539 method : "POST" ,
3640 headers : { "Content-Type" : "application/json" } ,
3741 body : JSON . stringify ( { nodeId, pubKey : publicKeyStr } ) ,
3842 } ) ;
3943
40- if ( ! response . ok ) {
41- throw new Error ( `Failed to register node ${ nodeId } ` ) ;
42- }
43-
44+ if ( ! registryResponse . ok ) throw new Error ( `Failed to register node: ${ registryResponse . statusText } ` ) ;
4445 console . log ( `Node ${ nodeId } registered successfully` ) ;
4546 } catch ( error ) {
4647 console . error ( "Failed to initialize node:" , error ) ;
4748 throw error ;
4849 }
4950
50- // Status route
51- onionRouter . get ( "/status" , ( req : Request , res : Response ) => {
52- res . send ( "live" ) ;
53- } ) ;
54-
55- // GET last received encrypted message
56- onionRouter . get ( "/getLastReceivedEncryptedMessage" , ( req : Request , res : Response ) => {
57- res . json ( { result : lastReceivedEncryptedMessage } ) ;
58- } ) ;
59-
60- // GET last received decrypted message
61- onionRouter . get ( "/getLastReceivedDecryptedMessage" , ( req : Request , res : Response ) => {
62- res . json ( { result : lastReceivedDecryptedMessage } ) ;
63- } ) ;
64-
65- // GET last message destination
66- onionRouter . get ( "/getLastMessageDestination" , ( req : Request , res : Response ) => {
67- res . json ( { result : lastMessageDestination } ) ;
68- } ) ;
69-
70- // Provide private key for testing purposes
71- onionRouter . get ( "/getPrivateKey" , ( req : Request , res : Response ) => {
72- res . json ( { result : privateKeyStr } ) ;
73- } ) ;
74-
75- const server = onionRouter . listen ( BASE_ONION_ROUTER_PORT + nodeId , ( ) => {
76- console . log ( `Onion router ${ nodeId } is listening on port ${ BASE_ONION_ROUTER_PORT + nodeId } ` ) ;
51+ onionRouter . get ( "/status" , ( req , res ) => res . send ( "live" ) ) ;
52+ onionRouter . get ( "/getLastReceivedEncryptedMessage" , ( req , res ) => res . json ( { result : lastReceivedEncryptedMessage } ) ) ;
53+ onionRouter . get ( "/getLastReceivedDecryptedMessage" , ( req , res ) => res . json ( { result : lastReceivedDecryptedMessage } ) ) ;
54+ onionRouter . get ( "/getLastMessageDestination" , ( req , res ) => res . json ( { result : lastMessageDestination } ) ) ;
55+ onionRouter . get ( "/getPrivateKey" , async ( req , res ) => res . json ( { result : privateKeyStr } ) ) ;
56+ onionRouter . get ( "/getLastCircuit" , ( req , res ) => res . json ( { result : lastCircuit } ) ) ;
57+
58+ onionRouter . post ( "/message" , async ( req , res ) => {
59+ try {
60+ const { message, circuit = [ ] } = req . body ;
61+ console . log ( `Node ${ nodeId } received message:` , message ) ;
62+
63+ if ( ! message ) return res . status ( 400 ) . json ( { error : "Message required" } ) ;
64+
65+ lastReceivedEncryptedMessage = message ;
66+ console . log ( `Last received encrypted message on Node ${ nodeId } :` , lastReceivedEncryptedMessage ) ;
67+
68+ const encryptedSymKey = message . slice ( 0 , 344 ) ;
69+ const encryptedPayload = message . slice ( 344 ) ;
70+
71+ let symKey ;
72+ try {
73+ const symKeyStr = await rsaDecrypt ( encryptedSymKey , privateKey ) ;
74+ symKey = await importSymKey ( symKeyStr ) ;
75+ } catch ( error ) {
76+ console . error ( `Node ${ nodeId } failed to decrypt symmetric key:` , error ) ;
77+ return res . status ( 500 ) . json ( { error : "Symmetric key decryption failed" } ) ;
78+ }
79+
80+ let decryptedPayload ;
81+ try {
82+ decryptedPayload = await symDecrypt ( await exportSymKey ( symKey ) , encryptedPayload ) ;
83+ } catch ( error ) {
84+ console . error ( `Node ${ nodeId } failed to decrypt payload:` , error ) ;
85+ return res . status ( 500 ) . json ( { error : "Payload decryption failed" } ) ;
86+ }
87+
88+ const destination = parseInt ( decryptedPayload . slice ( 0 , 10 ) , 10 ) ;
89+ const remainingMessage = decryptedPayload . slice ( 10 ) ;
90+
91+ lastReceivedDecryptedMessage = remainingMessage ;
92+ lastMessageDestination = destination ;
93+ lastCircuit = [ ...circuit , nodeId ] ;
94+
95+ await fetch ( `http://localhost:${ destination } /message` , {
96+ method : "POST" ,
97+ headers : { "Content-Type" : "application/json" } ,
98+ body : JSON . stringify ( { message : remainingMessage , circuit : lastCircuit } ) ,
99+ } ) ;
100+
101+ return res . json ( { success : true } ) ;
102+ } catch ( error ) {
103+ console . error ( "Error processing message:" , error ) ;
104+ return res . status ( 500 ) . json ( { error : "Failed to process message" } ) ;
105+ }
77106 } ) ;
78107
79- return server ;
108+ return onionRouter . listen ( BASE_ONION_ROUTER_PORT + nodeId , ( ) =>
109+ console . log ( `Onion router ${ nodeId } is listening on port ${ BASE_ONION_ROUTER_PORT + nodeId } ` )
110+ ) ;
80111}
0 commit comments