Skip to content

Commit 59b8fe1

Browse files
committed
Strict Kyber KeyEchange with transmit and recieve keys
1 parent 2aa5a52 commit 59b8fe1

File tree

17 files changed

+140
-80
lines changed

17 files changed

+140
-80
lines changed

profiles/profile.cert

0 Bytes
Binary file not shown.

scripts/certificates.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ await profile.saveToKeychain('profile.cert', `${dirname}/../profiles`, 'password
99
const UWCertificate = await domainCertificate({
1010
entity: 'universalweb.io',
1111
// ownerHash: profile.getSignature(),
12-
signatureAlgorithm: 3,
12+
signatureAlgorithm: 0,
1313
cipherSuites: [
14-
0,
15-
1,
14+
// 0,
1615
// 1,
17-
// 2,
16+
2,
1817
// 3
1918
],
20-
encryptionKeypairAlgorithm: 0,
19+
encryptionKeypairAlgorithm: 1,
2120
protocolOptions: {
2221
realtime: true,
2322
},

serverApp/certs/universalWeb.cert

-2.31 KB
Binary file not shown.
-706 Bytes
Binary file not shown.

todo.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,11 @@ Add universal request type that can handle all data sections params data could b
4343
consider hashing all prior generated keys into new ones
4444

4545
Avoid repeated Math limit packet math to cached only
46+
47+
Figure out and try and workout if you can avoid putting the protocol method id in the header when its not needed
48+
49+
Advertise UW devices on a local network (Announcement UPnP)
50+
51+
Disover Local Network UW devices
52+
53+
Ping packet - encrypted using domain certificates handshake/key exchange public key (mimic ICMP) (net-ping raw-socket)

udsp/client/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import {
4848
extendedHandshakeRPC,
4949
introRPC
5050
} from '../protocolFrameRPCs.js';
51-
import { extendedHandshake, sendExtendedHandshake } from './protocolEvents/extendedHandshake.js';
51+
import { extendedHandshake, sendExtendedHandshake, sendExtendedHandshakeHeader } from './protocolEvents/extendedHandshake.js';
5252
import {
5353
toBase64,
5454
toHex,
@@ -306,6 +306,7 @@ export class Client extends UDSP {
306306
intro = intro;
307307
extendedHandshake = extendedHandshake;
308308
sendExtendedHandshake = sendExtendedHandshake;
309+
sendExtendedHandshakeHeader = sendExtendedHandshakeHeader;
309310
async setSession(cipherData) {
310311
this.cipherSuite.clientSetSession(this, this.destination, cipherData);
311312
if (this.receiveKey) {
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
import { extendedHandshakeHeaderRPC } from '../../protocolHeaderRPCs.js';
2+
import { extendedHandshakeRPC } from '../../protocolFrameRPCs.js';
23
export async function sendExtendedHandshake(frame, header, rinfo) {
34
console.log('Sending Client Extended Handshake');
45
const { destination } = this;
5-
const extendedHandshakeHeader = [extendedHandshakeHeaderRPC];
6-
const extendedHandshakeFrame = await this.cipherSuite.sendClientExtendedHandshake(this, destination);
7-
await this.send(extendedHandshakeFrame, extendedHandshakeHeader);
6+
const targetHeader = [];
7+
const targetFrame = [false, extendedHandshakeRPC];
8+
await this.cipherSuite.sendClientExtendedHandshake(this, destination, targetFrame, targetHeader);
9+
await this.send(targetFrame, targetHeader);
10+
}
11+
export async function sendExtendedHandshakeHeader(frame, header, rinfo) {
12+
console.log('Sending Client Extended Handshake');
13+
const { destination } = this;
14+
const targetHeader = [extendedHandshakeHeaderRPC];
15+
const targetFrame = [];
16+
await this.cipherSuite.sendClientExtendedHandshakeHeader(this, destination, targetFrame, targetHeader);
17+
await this.send(targetFrame, targetHeader);
818
}
919
export async function extendedHandshake(frame, header, rinfo) {
1020
console.log('Client Extended Handshake');
1121
const { destination } = this;
12-
await this.cipherSuite.clientExtendedHandshake(this, destination);
22+
if (this.cipherSuite.clientExtendedHandshake) {
23+
await this.cipherSuite.clientExtendedHandshake(this, destination);
24+
}
1325
this.handshaked();
1426
}

udsp/client/protocolEvents/intro.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export async function introHeader(header, packetDecoded, rinfo) {
5959
if (packetDecoded.noMessage) {
6060
// Add Function that then receives the server extendedHandshakeHeader
6161
if (this.cipherSuite.sendClientExtendedHandshakeHeader) {
62-
this.cipherSuite.sendClientExtendedHandshakeHeader(this, this.destination, header, packetDecoded, rinfo);
62+
this.sendExtendedHandshakeHeader(this, this.destination, header, packetDecoded, rinfo);
6363
} else {
6464
this.handshaked();
6565
}
Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
// Closed source not for private and or corporate use.
2+
// KYBER KEY EXCHANGE WITH BUILT IN DOMAIN CERTIFICATE & SERVER AUTHENTICATION WITH Perfect Forward Secrecy
3+
/*
4+
Create User Kyber keypair send to server
5+
Server creates Kyber shared Secret & encapsulates it via user's public kyber key
6+
Server sends cipher text in the header & encrypted intro frame to the user
7+
Server sets the session with the new secret keys
8+
User first decapsulates ciphertext with user's private kyber key located in the header
9+
User then sets the session with the new secret keys
10+
Make sure to create a transmit and receive keys so both are unique to add an extra layer of security
11+
*/
212
import * as defaultCrypto from '#crypto';
313
import { assign, clear, isBuffer } from '@universalweb/acid';
414
import {
5-
decapsulate, encapsulate, encryptionKeypair, kyber768
15+
decapsulate,
16+
encapsulate,
17+
encryptionKeypair,
18+
kyber768
619
} from '../keyExchange/kyber768.js';
720
import { decrypt, encrypt } from '../encryption/XChaCha.js';
21+
import { extendedHandshakeHeaderRPC, introHeaderRPC } from '../../protocolHeaderRPCs.js';
22+
import { extendedHandshakeRPC, introRPC } from '../../protocolFrameRPCs.js';
823
import { blake3 } from '@noble/hashes/blake3';
9-
import { extendedHandshakeRPC } from '../../../udsp/protocolFrameRPCs.js';
10-
import { introHeaderRPC } from '../../protocolHeaderRPCs.js';
1124
import { ml_kem768 } from '@noble/post-quantum/ml-kem';
1225
const {
1326
randomConnectionId,
@@ -20,13 +33,6 @@ const {
2033
} = defaultCrypto;
2134
const { id: encryptionKeypairID, } = kyber768;
2235
const hash = blake3;
23-
// Create User Kyber keypair send to server
24-
// Server creates Kyber shared Secret & encapsulates it via user's public kyber key
25-
// Server sends cipher text in the header & encrypted intro frame to the user
26-
// Server sets the session with the new secret keys
27-
// User first decapsulates ciphertext with user's private kyber key located in the header
28-
// User then sets the session with the new secret keys
29-
// PRIORITY: Make sure to swap Transmit and Receive keys so both are unique to add an extra layer of security
3036
export const kyber768_xChaCha = {
3137
name: 'kyber768_xChaCha',
3238
alias: 'kyber768',
@@ -43,45 +49,56 @@ export const kyber768_xChaCha = {
4349
console.log('clientInitializeSession Destination', destination);
4450
console.log('Public Key from destination', destination.publicKey[0]);
4551
},
46-
async sendClientExtendedHandshake(source, destination) {
52+
async clientSetSession(source, destination, cipherData) {
53+
const kyberPrivateKey = source.privateKey;
54+
const sharedSecret = await decapsulate(cipherData, kyberPrivateKey);
55+
console.log('clientSetSession kyberSharedSecret', sharedSecret[0], sharedSecret.length);
56+
source.transmitKey = sharedSecret;
57+
source.receiveKey = hash(sharedSecret);
58+
console.log('New Session Keys', source.transmitKey[0], source.receiveKey[0]);
59+
},
60+
async sendClientExtendedHandshake(source, destination, frame, header) {
4761
const destinationPublicKey = destination.publicKey;
4862
console.log('TRIGGERED sendClientExtendedHandshake');
4963
console.log(destinationPublicKey.length);
5064
const {
5165
cipherText,
5266
sharedSecret
5367
} = await encapsulate(destinationPublicKey);
54-
const frame = [
55-
false,
56-
extendedHandshakeRPC,
57-
cipherText
58-
];
68+
frame.push(cipherText);
5969
source.cipherData = cipherText;
6070
source.sharedSecret = sharedSecret;
6171
console.log('sendClientExtendedHandshake kyberSharedSecret', sharedSecret[0], sharedSecret.length);
6272
console.log('sendClientExtendedHandshake cipherText', cipherText[0], cipherText.length);
63-
return frame;
6473
},
6574
async clientExtendedHandshake(source, destination) {
6675
console.log('TRIGGERED client ExtendedHandshake', source.transmitKey, source.sharedSecret);
76+
const sharedSecret = source.sharedSecret;
6777
const oldTransmitKey = source.transmitKey;
78+
const oldReceiveKey = source.receiveKey;
6879
source.transmitKey = combineKeys(oldTransmitKey, source.sharedSecret);
69-
source.receiveKey = source.transmitKey;
80+
source.receiveKey = combineKeys(oldReceiveKey, source.sharedSecret);
7081
clearBuffer(oldTransmitKey);
82+
clearBuffer(oldReceiveKey);
7183
clearBuffer(source.sharedSecret);
7284
clearBuffer(source.cipherData);
7385
source.sharedSecret = null;
7486
source.cipherData = null;
7587
console.log('TRIGGERED client ExtendedHandshake', source.transmitKey);
7688
},
77-
async clientSetSession(source, destination, cipherData) {
78-
const kyberPrivateKey = source.privateKey;
79-
const sharedSecret = await decapsulate(cipherData, kyberPrivateKey);
80-
source.transmitKey = sharedSecret;
81-
source.receiveKey = source.transmitKey;
82-
console.log('clientSetSession kyberSharedSecret', sharedSecret[0], sharedSecret.length);
83-
console.log('Keys', source.transmitKey[0], source.receiveKey[0]);
84-
},
89+
// async clientSetSession(source, destination, cipherData) {
90+
// const kyberPrivateKey = source.privateKey;
91+
// const sharedSecret = await decapsulate(cipherData, kyberPrivateKey);
92+
// console.log('clientSetSession kyberSharedSecret', sharedSecret[0], sharedSecret.length);
93+
// const oldTransmitKey = source.transmitKey;
94+
// const oldReceiveKey = source.receiveKey;
95+
// console.log('Old Session Keys', source.transmitKey[0], source.receiveKey[0]);
96+
// source.transmitKey = combineKeys(oldTransmitKey, source.sharedSecret);
97+
// source.receiveKey = combineKeys(oldReceiveKey, source.sharedSecret);
98+
// clearBuffer(oldTransmitKey);
99+
// clearBuffer(oldReceiveKey);
100+
// console.log('New Session Keys', source.transmitKey[0], source.receiveKey[0]);
101+
// },
85102
async serverInitializeSession(source, destination, destinationPublicKey) {
86103
console.log('server InitializeSession');
87104
console.log(destinationPublicKey);
@@ -91,7 +108,7 @@ export const kyber768_xChaCha = {
91108
} = await encapsulate(destinationPublicKey);
92109
destination.publicKey = destinationPublicKey;
93110
source.cipherData = cipherText;
94-
source.transmitKey = sharedSecret;
111+
source.transmitKey = hash(sharedSecret);
95112
source.receiveKey = sharedSecret;
96113
console.log('server kyberSharedSecret', sharedSecret[0], sharedSecret.length);
97114
console.log('destinationPublicKey', destinationPublicKey[0]);
@@ -102,44 +119,43 @@ export const kyber768_xChaCha = {
102119
header[1] = source.cipherData;
103120
},
104121
async serverExtendedHandshake(source, destination, frame, header) {
105-
if (!source.sharedSecret) {
106-
console.log('serverExtendedHandshake CIPHER CALLED', frame, header);
107-
const [
108-
streamid_undefined,
109-
rpc,
110-
cipherData
111-
] = frame;
112-
const privateKey = source.privateKey;
113-
const sharedSecret = await decapsulate(cipherData, privateKey);
114-
clearBuffer(source.cipherData);
115-
source.cipherData = null;
116-
source.sharedSecret = sharedSecret;
117-
source.nextSession = true;
118-
console.log('Keys', source.transmitKey[0], source.receiveKey[0]);
119-
console.log('sharedSecret', source.sharedSecret[0]);
120-
console.log('server cipherText', cipherData[0], cipherData.length);
121-
}
122+
console.log('serverExtendedHandshake CIPHER CALLED', frame, header);
123+
const [
124+
streamid_undefined,
125+
rpc,
126+
cipherData
127+
] = frame;
128+
const privateKey = source.privateKey;
129+
const sharedSecret = await decapsulate(cipherData, privateKey);
130+
clearBuffer(cipherData);
131+
source.cipherData = null;
132+
source.sharedSecret = sharedSecret;
133+
source.nextSession = true;
134+
console.log('Keys', source.transmitKey[0], source.receiveKey[0]);
135+
console.log('sharedSecret', source.sharedSecret[0]);
136+
console.log('server cipherText', cipherData[0], cipherData.length);
122137
},
123138
async sendServerExtendedHandshake(source, destination) {
124-
const frame = [
125-
false,
126-
extendedHandshakeRPC,
127-
];
128-
return frame;
139+
console.log('Server Extended Handshake ack');
140+
// Should be able to remove this
141+
// const frame = [
142+
// false,
143+
// extendedHandshakeRPC,
144+
// ];
145+
// return frame;
129146
},
130147
async serverSetSession(source, destination) {
131148
console.log('serverSetSession');
132149
const sharedSecret = source.sharedSecret;
133150
const oldTransmitKey = source.transmitKey;
134-
source.transmitKey = combineKeys(oldTransmitKey, sharedSecret);
135-
source.receiveKey = source.transmitKey;
151+
const oldReceiveKey = source.receiveKey;
152+
source.transmitKey = combineKeys(oldTransmitKey, source.sharedSecret);
153+
source.receiveKey = combineKeys(oldReceiveKey, source.sharedSecret);
136154
clearBuffer(oldTransmitKey);
137-
clearBuffer(source.sharedSecret);
138-
clearBuffer(source.cipherData);
155+
clearBuffer(oldReceiveKey);
139156
clearBuffer(source.sharedSecret);
140157
source.sharedSecret = null;
141158
source.nextSession = null;
142-
console.log('kyberSharedSecret', sharedSecret[0]);
143159
console.log('Keys', source.transmitKey[0], source.receiveKey[0]);
144160
},
145161
generateSeed() {
@@ -160,3 +176,4 @@ export const kyber768_xChaCha = {
160176
extendedHandshake: true,
161177
encryptionKeypairID,
162178
};
179+
// copyright © Thomas Marchi

udsp/cryptoMiddleware/cipherSuite/x25519_Kyber768Half_xChaCha.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,4 @@ export const x25519_kyber768Half_xchacha20 = {
125125
decrypt,
126126
encrypt,
127127
};
128+
// copyright © Thomas Marchi

0 commit comments

Comments
 (0)