Skip to content

Commit

Permalink
New Certificate API
Browse files Browse the repository at this point in the history
Cryptography Middleware Updated
New Handshake Process with 2 packets
Start of get Certificate from Server during handshake
verbose logging
code cleanup
Dependencies Updated
  • Loading branch information
Universal Web committed Jul 26, 2023
1 parent d414709 commit 3b8b135
Show file tree
Hide file tree
Showing 24 changed files with 181 additions and 140 deletions.
Binary file modified profiles/default-Ephemeral.cert
Binary file not shown.
Binary file modified profiles/default-EphemeralPublic.cert
Binary file not shown.
Binary file modified profiles/default-Master.cert
Binary file not shown.
Binary file modified profiles/default-MasterPublic.cert
Binary file not shown.
Binary file modified profiles/default-Profile.cert
Binary file not shown.
4 changes: 2 additions & 2 deletions scripts/certificates.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ const domainProfile = await createProfile({
signature: 'ed25519',
exchange: 'x25519',
curve: '25519',
// The cryptographic algo used, intended, and or generated with the provided public key
publicKeyType: 'ed25519',
// The purpose of encrypting connection IDs is to eliminate CID tracking and to constantly change how the CID looks.
// Encrypting CIDs protects against leaking smart CID routing information which show the endpoint server/process.
// encryptConnectionId: 'sealedbox', Applies to both client and server connection ID
Expand Down Expand Up @@ -91,6 +89,8 @@ const domainProfile = await createProfile({
// headerCompression: true,
// footerCompression: true,
autoLogin: true,
// The cryptographic algo used, intended, and or generated with the provided public key
keypairType: 'ed25519',
},
master: {},
},
Expand Down
6 changes: 4 additions & 2 deletions serverApp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ const appServer = await server({
// Max retries for a singular request before giving up
maxResponseRetries: 3,
// Max size of packets
maxPacketSize: 1100,
// maxPacketSize: 1100,
// Max size of body and head data sections in a single packet
maxPacketPayloadSize: 1000,
// maxPayloadSize: 1000,
// max file size
maxFileSize: 9000,
// Max size of a Response
Expand All @@ -33,6 +33,8 @@ const appServer = await server({
defaultExtension: 'html',
// Domain certificate to be loaded used for connection encryption
certificate: path.join(currentPath(import.meta), '../services/universal.web-Ephemeral.cert'),
// Public Domain certificate to be sent in its raw format for validation when a client connects but doesn't have a certificate
certificatePublic: path.join(currentPath(import.meta), '../services/universal.web-EphemeralPublic.cert'),
// Where to load app resources from
resourceDirectory: path.join(currentPath(import.meta), 'resources'),
// Server ID used for load balancing and attaching to the end of connection IDs
Expand Down
Binary file modified services/universal.web-Ephemeral.cert
Binary file not shown.
Binary file modified services/universal.web-EphemeralPublic.cert
Binary file not shown.
Binary file modified services/universal.web-Master.cert
Binary file not shown.
Binary file modified services/universal.web-MasterPublic.cert
Binary file not shown.
Binary file modified services/universal.web-Profile.cert
Binary file not shown.
11 changes: 8 additions & 3 deletions udsp/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,21 @@ export class UDSP {
this.maxPayloadSize = this.maxPacketSize - this.packetOverhead;
this.maxPayloadSizeSafeEstimate = this.maxPayloadSize - 10;
if (!maxDataSize) {
this.maxDataSize = this.packetMaxPayload;
this.maxDataSize = this.maxPayloadSize;
}
if (!maxHeadSize) {
this.maxHeadSize = this.packetMaxPayload;
this.maxHeadSize = this.maxPayloadSize;
}
console.log(`packetInitialOverhead: ${packetInitialOverhead} bytes`);
}
console.log(`encryptPacketOverhead: ${this.encryptPacketOverhead} bytes`);
console.log(`Packet Overhead: ${this.packetOverhead} bytes`);
console.log(`connectionIdSize Overhead: ${this.connectionIdSize} bytes`);
console.log(`Max Packet Size: ${this.maxPacketSize} bytes`);
console.log(`Max Payload Size Safe Estimate: ${this.maxPayloadSizeSafeEstimate} bytes`);
console.log(`Max Payload Size: ${this.maxPayloadSize} bytes`);
console.log(`Max Data Size: ${this.maxDataSize} bytes`);
console.log(`Max Head Size: ${this.maxHeadSize} bytes`);
console.log(`Max Packet Size: ${this.maxPacketSize} bytes`);
}
generateConnectionID() {
const target = randomConnectionId(this.connectionIdSize || 8);
Expand Down
131 changes: 71 additions & 60 deletions udsp/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ import {
isString,
promise,
isTrue,
currentPath
currentPath,
hasValue
} from '@universalweb/acid';
import dgram from 'dgram';
import { success, configure, info } from '#logs';
import {
keypair,
toBase64,
emptyNonce,
randomConnectionId,
clientSessionKeys,
signPublicKeyToEncryptPublicKey
} from '#crypto';
import { getCertificate, parseCertificate } from '#certificate';
import { watch } from '#watch';
Expand Down Expand Up @@ -72,6 +70,7 @@ export class Client extends UDSP {
// console.log('Loading Destination Certificate', destinationCertificate);
const certificate = await getCertificate(destinationCertificate);
assign(destination, certificate);
this.hasCertificate = true;
}
if (!destination.publicKey) {
console.log('No destination certificate provided.');
Expand Down Expand Up @@ -111,6 +110,7 @@ export class Client extends UDSP {
clientSessionKeys: true,
}
}, destination);
console.log(cryptoConfig);
this.cryptography = await cryptography(cryptoConfig);
if (this.cryptography.encryptionKeypair) {
this.destination.encryptKeypair = this.cryptography.encryptionKeypair;
Expand All @@ -129,12 +129,7 @@ export class Client extends UDSP {
this.connectionIdKeypair = this.cryptography.generated.connectionIdKeypair;
success(`Created Connection Keypair`);
}
this.sessionKeys = this.cryptography.generated.sessionKeys;
if (this.sessionKeys) {
success(`Created Shared Keys`);
success(`receiveKey: ${toBase64(this.sessionKeys.receiveKey)}`);
success(`transmitKey: ${toBase64(this.sessionKeys.transmitKey)}`);
}
this.setSessionKeys(this.cryptography.generated.sessionKeys);
}
async attachEvents() {
const thisClient = this;
Expand Down Expand Up @@ -184,46 +179,61 @@ export class Client extends UDSP {
const ask = construct(Ask, [message, options, this]);
return ask;
}
sendIntro(ask) {
console.log('Sending Intro');
const header = this.setPublicKeyHeader();
const message = {
intro: true
};
this.introSent = true;
this.send(message, header);
loadCertificate(certificate) {
this.destination.certificate = parseCertificate(certificate);
this.configCryptography();
}
proccessCertificateChunk(message) {
const {
pid,
cert,
last
} = message;
this.certChunks[pid] = cert;
if (last) {
this.loadCertificate(Buffer.concat(this.certChunks));
this.handshakeCompletedEvent(message);
}
}
setSessionKeys(generatedKeys) {
this.sessionKeys = generatedKeys || this.cryptography.clientSessionKeys(this.encryptKeypair, this.destination.encryptKeypair);
if (this.sessionKeys) {
success(`Created Shared Keys`);
success(`receiveKey: ${toBase64(this.sessionKeys.receiveKey)}`);
success(`transmitKey: ${toBase64(this.sessionKeys.transmitKey)}`);
}
}
handshakeCompletedEvent(message) {
console.log('Handshake Completed');
this.connected = true;
this.state = 2;
// Resolve the handshake promise
this.handshakeCompleted(message);
}
serverIntro(message) {
console.log('Got server Intro', message);
this.state = 1;
const {
scid: serverConnectionId,
reKey
reKey,
certSize,
cert
} = message;
this.serverIntroReceived = true;
this.destination.id = serverConnectionId;
this.destination.encryptKeypair = {
publicKey: reKey
};
this.destination.sessionKeys = this.cryptography.clientSessionKeys(this.encryptKeypair, reKey);
this.confirmReKey();
}
confirmReKey() {
console.log('Sending rekey confirmation');
const header = {};
const message = {
confirmClientReKey: true
};
this.confirmRekey = true;
this.send(message, header);
}
endHandshake(message) {
console.log('Handshake Completed');
const { handshake } = message;
console.log('Handshake Finished', handshake);
this.connected = true;
// Trigger the handshake completed event
this.handshakeCompleted(message);
this.setSessionKeys();
if (cert) {
this.certChunks[0] = cert;
this.loadCertificate(Buffer.concat(this.certChunks));
}
if (hasValue(certSize)) {
this.certSize = certSize;
}
if (!certSize) {
this.handshakeCompletedEvent(message);
}
}
setPublicKeyHeader(header = {}) {
const key = this.encryptKeypair.publicKey;
Expand All @@ -236,18 +246,25 @@ export class Client extends UDSP {
}
return header;
}
launchHandshake() {
this.awaitHandshake = promise((accept) => {
this.handshakeCompleted = accept;
});
this.sendIntro();
return this.awaitHandshake;
sendIntro() {
console.log('Sending Intro');
this.state = 1;
const header = this.setPublicKeyHeader();
const requestCertificate = Boolean(this.hasCertificate);
const message = {
intro: true
};
this.introSent = true;
this.send(message, header);
}
ensureHandshake() {
if (this.connected === true) {
return true;
} else if (!this.handshakeCompleted) {
this.launchHandshake();
this.awaitHandshake = promise((accept) => {
this.handshakeCompleted = accept;
});
this.sendIntro();
}
return this.awaitHandshake;
}
Expand All @@ -258,24 +275,17 @@ export class Client extends UDSP {
proccessProtocolPacket(message) {
const {
intro,
serverIntro,
confirmClientReKey,
handshake
certIndex,
} = message;
console.log('Processing Protocol Packet');
if (intro) {
this.sendServerIntro(message);
} else if (serverIntro) {
this.serverIntro(message);
} else if (confirmClientReKey) {
this.confirmClientReKey(message);
} else if (handshake) {
this.endHandshake(message);
if (certIndex) {
this.proccessCertificateChunk(message);
} else {
this.serverIntro(message);
}
}
}
loadCertificate(certificate) {
this.certificates = certificate;
this.configCryptography();
}
request = request;
fetch = fetchRequest;
processMessage = processMessage;
Expand All @@ -286,6 +296,7 @@ export class Client extends UDSP {
autoConnect = false;
static connections = new Map();
packetIdGenerator = construct(UniqID);
certChunks = [];
}
export async function client(configuration) {
console.log('Create Client');
Expand Down
16 changes: 5 additions & 11 deletions udsp/client/onPacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,28 @@ import {
import { decode } from 'msgpackr';
import { decrypt, createSessionKey } from '#crypto';
import { decodePacket, decodePacketHeaders } from '#udsp/decodePacket';
imported('Server onMessage');
import { processMessage } from './processMessage.js';
import { hasValue } from '@universalweb/acid';
export async function onPacket(packet) {
const { destination: source } = this;
msgReceived('Packet Received');
const config = {
destination: this,
source,
source: this.destination,
packet,
};
const wasHeadersDecoded = await decodePacketHeaders(config);
if (!wasHeadersDecoded || !config.packetDecoded.header) {
return failed('Invalid Packet Headers');
return failed('Error failed to decode packet headers');
}
const wasDecoded = await decodePacket(config);
if (!wasDecoded) {
return failed('When decoding the packet but header passed');
}
if (this.state === 0) {
if (!config.packetDecoded.error) {
this.state = 1;
}
return failed('Error when decoding the packet but header was decoded');
}
const {
header,
message
} = config.packetDecoded;
if (message.sid) {
if (hasValue(message?.sid)) {
processMessage(config.packetDecoded, this);
} else {
this.proccessProtocolPacket(message, header);
Expand Down
29 changes: 12 additions & 17 deletions udsp/client/processMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
stringify,
hasValue
} from '@universalweb/acid';
imported('Client ProcessMessage');
export async function processMessage(packet, client) {
const {
header,
Expand All @@ -14,29 +13,25 @@ export async function processMessage(packet, client) {
} = packet;
const { queue } = client;
const {
connectionClose,
state,
sid,
} = message;
info(`Packet Received Stream ID: ${sid}`);
if (state) {
console.log(`STATE CODE: ${state}`);
}
if (message) {
if (message.state === 3) {
client.close();
return failed(`End event sent disconnected socket`);
}
if (hasValue(sid)) {
info(`Stream ID: ${sid} ${stringify(message)}`);
console.log(queue.keys());
const askObject = queue.get(sid);
if (askObject) {
askObject.onPacket(packet);
} else {
return failed(`Invalid Stream Id given. ${stringify(message)}`);
}
}
if (state === 3 || connectionClose) {
client.close();
return failed(`End event received from server disconnected closing client`);
}
// console.log(queue.keys());
const askObject = queue.get(sid);
if (askObject) {
askObject.onPacket(packet);
} else {
console.log('NO MESSAGE OBJECT', packet);
failed(`Invalid Stream Id given no ask object with that ID. ${sid}`);
console.log(message);
}
}

Loading

0 comments on commit 3b8b135

Please sign in to comment.